7.2 Git Tools - Interactive Staging

Interactive Staging

Git comes with a couple of scripts that make some command-line tasks easier.
Here, you’ll look at a few interactive commands that can help you easily craft your commits to include only certain combinations and parts of files.
These tools are very helpful if you modify a bunch of files and then decide that you want those changes to be in several focused commits rather than one big messy commit.
This way, you can make sure your commits are logically separate changesets and can be easily reviewed by the developers working with you.
If you run git add with the -i or --interactive option, Git goes into an interactive shell mode, displaying something like this:

You can see that this command shows you a much different view of your staging area – basically the same information you get with git status but a bit more succinct and informative.
It lists the changes you’ve staged on the left and unstaged changes on the right.

After this comes a Commands section.
Here you can do a number of things, including staging files, unstaging files, staging parts of files, adding untracked files, and seeing diffs of what has been staged.

To see the diff of what you’ve staged, you can use the 6 or d (for diff) command.
It shows you a list of your staged files, and you can select the ones for which you would like to see the staged diff.
This is much like specifying git diff --cached on the command line:

It’s also possible for Git to stage certain parts of files and not the rest.
For example, if you make two changes to your simplegit.rb file and want to stage one of them and not the other, doing so is very easy in Git.
From the interactive prompt, type 5 or p (for patch).
Git will ask you which files you would like to partially stage; then, for each section of the selected files, it will display hunks of the file diff and ask if you would like to stage them, one by one:

You have a lot of options at this point.
Typing ? shows a list of what you can do:

Stage this hunk [y,n,a,d,/,j,J,g,e,?]? ?y - stage this hunkn - do not stage this hunka - stage this and all the remaining hunks in the filed - do not stage this hunk nor any of the remaining hunks in the fileg - select a hunk to go to/ - search for a hunk matching the given regexj - leave this hunk undecided, see next undecided hunkJ - leave this hunk undecided, see next hunkk - leave this hunk undecided, see previous undecided hunkK - leave this hunk undecided, see previous hunks - split the current hunk into smaller hunkse - manually edit the current hunk? - print help

Generally, you’ll type y or n if you want to stage each hunk, but staging all of them in certain files or skipping a hunk decision until later can be helpful too.
If you stage one part of the file and leave another part unstaged, your status output will look like this:

The status of the simplegit.rb file is interesting.
It shows you that a couple of lines are staged and a couple are unstaged.
You’ve partially staged this file.
At this point, you can exit the interactive adding script and run git commit to commit the partially staged files.

You also don’t need to be in interactive add mode to do the partial-file staging – you can start the same script by using git add -p or git add --patch on the command line.

Furthermore, you can use patch mode for partially resetting files with the reset --patch command, for checking out parts of files with the checkout --patch command and for stashing parts of files with the stash save --patch command.
We’ll go into more details on each of these as we get to more advanced usages of these commands.