Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stage visual selection (add -p) #269

Open
gilligan opened this issue Nov 10, 2012 · 29 comments
Open

Stage visual selection (add -p) #269

gilligan opened this issue Nov 10, 2012 · 29 comments
Labels
enhancement New feature or request

Comments

@gilligan
Copy link

It would be great if fugitive could provide a mapping to stage the current visual selection of a file.

Obviously there is no straight forward way to achieve this. The only approach I could find is something that I found on stackoverflow and it involves fiddling around with the index behind git add's back
(http://stackoverflow.com/a/2785039/457853):

#!/bin/sh

start_line=$1
end_line=$2
path=$3

mode=$(git ls-files -s $path | awk '{print $1}')
blob_id=$(
    (
        head -n $(expr $start_line - 1) $path
        cat
        tail -n +$(expr $end_line + 1) $path
        ) | git hash-object -w --stdin
    )
exec git update-index --cacheinfo $mode $blob_id $path

Maybe there are other ways to achieve the same? In either case it would be a feature that
I would love to see.

@tpope
Copy link
Owner

tpope commented Nov 11, 2012

Won't that only work if there have been no line additions or deletions in the file?

@ohcibi
Copy link

ohcibi commented Feb 14, 2013

I don't know if I'm misunderstanding something, but in the screencasts mentioned in README.md I learned, that in :Gdiff you'd just :diffput to the index version of the file and then save that index, leading to the :diffputed changes beeing staged, pretty straightforward imo. I'm doing it always like this as sometimes I can do it even more specific than with plain add -p (some chunks are not splittable, but perhaps I'm missing something on the git side here).

A function for directly staging visual-selected lines (without the need to :Gdiff etc.) would be nice though.

@martinklepsch
Copy link

Was just looking if this is possible and I think it would be a quite useful feature as well 👍

@martinfinke
Copy link

Yeah, I think so too! 👍

SourceTree can do this, it can even discard a selected range of lines:

SourceTree Stage Selected Lines Screenshot

@teoljungberg
Copy link
Contributor

You can achieve this using :Gdiff with :diffput and :diffget

  1. Fire up :Gdiff
  2. Visually select the change/line you want to stage. :diffput
  3. Profit

From, this vimcasts episode: http://vimcasts.org/episodes/fugitive-vim-working-with-the-git-index/

@martinfinke
Copy link

Awesome! Thanks 👍

@var-const
Copy link

I would also be very happy if such a feature was added. Using :Gdiff works but is a little clunky.

@mcepl
Copy link
Contributor

mcepl commented May 22, 2016

Using :Gdiff works but is a little clunky.

Could you elaborate on “clunky”, please?

@ohcibi
Copy link

ohcibi commented May 23, 2016

@mcepl the workflow is:

  1. mark lines to be staged
  2. use diffget/put or anything to copy over to index file (which one was the index again?)
  3. save the index file

This feels overcomplicated when I just want to "stage these lines". It is already possible to stage the current file with :Gwrite so a :'<,'>Gwrite to stage the current selection feels kind of natural.

@mcepl
Copy link
Contributor

mcepl commented May 30, 2016

This feels overcomplicated when I just want to "stage these lines". It is already possible to stage the current file with :Gwrite so a :'<,'>Gwrite to stage the current selection feels kind of natural.

I kind of like the additional security in knowing that before I write Gwrite nothing actually gets changed.

@edubxb
Copy link

edubxb commented Oct 3, 2016

The GitGutter plugin has this feature:

https://github.com/airblade/vim-gitgutter#hunks

very useful IMHO.

@simonweil
Copy link

Would like this too

@sondnm
Copy link

sondnm commented Feb 21, 2019

Hi. Do you have any updates on this feature?

BTW thanks a lot for your awesome plugins!

@tpope
Copy link
Owner

tpope commented Feb 21, 2019

My update is I asked a question 6 years ago and nobody answered it.

@sondnm
Copy link

sondnm commented Feb 22, 2019

Won't that only work if there have been no line additions or deletions in the file?

I see your point there. I have tried the script on deletion and it doesn't work.
The workflow using diffput on :Gdiff on the other hand is quite simple to use.

@tpope
Copy link
Owner

tpope commented Feb 24, 2019

It would certainly be possible to filter the lines in git diff to only include the provided range and feed the result to git apply --index. It'd still be kind of weird that we're writing the entire work tree file but only part of the index file, but I guess that's what people would naturally expect to happen.

@sondnm
Copy link

sondnm commented Feb 27, 2019

As I understood, the Gwrite will stage the whole work tree file and git apply --index only change part of the index file. What would be the consequences if we do this in your opinion?

@tpope
Copy link
Owner

tpope commented Aug 13, 2019

If the file is already written to disk, the way to do this is to git diff the file, modify that patch to exclude lines outside the range by looking at hunk headers and doing some counting, and git apply --cached it. We do something similar for inline diffs in the :Gstatus window, although "excluding lines outside the range" means something very different there. If someone implements the `"modify that patch" bit, I can probably glue the rest together.

If the file has unwritten changes, that raises a bunch of questions, but I'd be fine to accept "write the entire file to the work tree first" as the path of least resistance.

@sondnm The consequence I was alluding to is that someone might expect :1,2Gwrite to behave like :1,2write, effectively deleting all but the first 2 lines. But I've come to the decision that's silly and we can ignore it.

@bam80
Copy link

bam80 commented Aug 13, 2019

modify that patch to exclude lines outside the range by looking at hunk headers and doing some counting
maybe we could use external utility for that: Quilt (software)

@tpope
Copy link
Owner

tpope commented Aug 13, 2019

I will not accept an external dependency to avoid "looking at hunk headers and doing some counting". This isn't hard, it's just tedious.

@bam80
Copy link

bam80 commented Aug 13, 2019

Makes sense. Maybe we could borrow the code from it then.

@dagadbm
Copy link

dagadbm commented Feb 14, 2020

I guess what is missing here is on the GStatus window when i open the file with enter i just enter a the fugitive diff mode and then stage the chunks from them?

@dagadbm
Copy link

dagadbm commented Feb 14, 2020

As a current workout around just press I on the status file right?

@tpope
Copy link
Owner

tpope commented Feb 14, 2020

I guess what is missing here is on the GStatus window when i open the file with enter i just enter a the fugitive diff mode and then stage the chunks from them?

You can do this in one step by pressing dd on the file.

As a current workout around just press I on the status file right?

That's less of a workaround and more of an alternative workflow, and as far as alternative workflows go, I'd sooner recommend pressing =.

@flavius
Copy link

flavius commented Apr 17, 2020

@tpope There's a real UX issue hidden behind this issue, and that is if you have the Gstatus open, you press enter, you go to the file to review the changes, you review and choose to stage specific hunks with diffput or whatever, then everything ok so far.

BUT

then you go to the status window to proceed with the hunks in the next file. The moment you press enter, the window with the staged version goes away, and you have to type again :Gdiff.

This destroys the overall flow which you actually have with git add -pv.

I'd rather take a step back and look at the flow in its entirety and make fugitive provide added value where it shines.

For me, that is breaking out of the linear flow which I have in the terminal, for instance seeing the git status and the code at the same time.

Also sometimes, I simply know what I want to stage, once I'm in a file and I see the whole context (thanks fugitive), doing :Gdiff is just additional fluff.

Staging the selected range would improve the workflow immensly without giving up on the advantages of using fugitive.

Think about it for a moment, how many keystrokes does a git add -pv user invest? The goal of fugitive should be to reduce that count (which it does naturally, because it breaks out of the linearity), but then you throw a compulsory :Gdiff in there and by doing so you throw away all the hanging fruit.

Yet, I still appreciate the nonlinearity of fugitive, it would just speed me up if it would play along with the rest of the flow.

@tpope
Copy link
Owner

tpope commented Apr 17, 2020

@tpope There's a real UX issue hidden behind this issue, and that is if you have the Gstatus open, you press enter, you go to the file to review the changes, you review and choose to stage specific hunks with diffput or whatever, then everything ok so far.

BUT

then you go to the status window to proceed with the hunks in the next file. The moment you press enter, the window with the staged version goes away, and you have to type again :Gdiff.

You can do this in one step by pressing dd on the file.

You can do this in one step by pressing dd on the file.

You can do this in one step by pressing dd on the file.

You can do this in one step by pressing dd on the file.

You can do this in one step by pressing dd on the file.

There, now hopefully everyone will actually see it.

Staging the selected range would improve the workflow immensly without giving up on the advantages of using fugitive.

I've already given advice on what's needed to implement it, so it's hard to read this as anything other than nagging me to do it myself. That will get you nowhere.

@TamaMcGlinn
Copy link

Side-note: in the Gstatus window, you can press = on a file to show all changes, do a line selection shift-v in there, and press s to stage just those lines (even they are a subset of a hunk). This is quite a nice final-review flow, using gU and then cntrl-N / cntrl-P and toggling =, and staging everything from within the Gstatus window.

@PANCHOHACK
Copy link

Ya lo lograron

@PANCHOHACK
Copy link

Estoy esperando ha que acaben de desinflar mi contenido para irme a mi otro cel y kmplementar más candados en este perfil jajaja si lo que puse aki es algo básico kieren algo más difícil?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests