If you have ever used made extensive use of GUI interfaces for git you may have come across the ability to stage and commit only parts of your changes to files rather than committing everything that you changed in said files at once. Recently I learned that the command-line interface to git supports the same feature using the -p flag when staging or even committing files which is what I briefly want to go through in this article.
Staging partial changes
For this example I have initialized an empty git repository and have committed a README.txt file with it with the following contents:
# Dummy Project This is a README, there are many like it but this one belongs to the Dummy Project.
Three features are in development for this Dummy Project which I have described in the README, however I decided that I am at this moment only ready to commit the first and third features. You can paste the text from below into your own version of README.txt if you want to follow along:
# Feature 1 This section is about feature 1. # Feature 2 This section is about feature 2. # Feature 3 This section is about feature 3.
When checking out the changes in the README.txt file it should look like this:
To only stage the sections “Feature 1” and “Feature 3” we can use
git add -p like shown in the below image.
Git has now started an interactive dialog where we can decide what to do with each change in the selected file(s).
By entering ? (and hitting enter) the options we have are explained. In our case we want to edit the hunk using the e option.
The e option opened the hunk in the shell’s default editor, for me this is Vim (you can set your preferred editor by specifying the EDITOR environment variable in your shell’s settings).
Following the instructions shown in the bottom I commented out the lines for “Feature 2” to exclude them (I found that deleting them has the same effect, I prefer commenting them out though as this gives me better insight into what I am doing exactly). To complete the edit you have to write the changes.
Checking the status after completing the interactive process shows that README.txt has been staged for commit and also has unstaged changes.
Looking at the staged changes you will find that this matches what we staged during the interactive process:
And the unstaged changes are what we left out:
And the file itself is (as you would expect from the previous diff command) intact:
Running “git commit” will now commit the staged changes.
Leaving you with only the unstaged changes after commit (as one would expect):
Directly committing partial changes
If you are feeling particularly sure of yourself you can use the -p flag on the git commit command instead of using git add first. If we start over with the process of the previous section (you can undo your last commit with
git reset HEAD~1 to follow along) it would go like this.
The end result of the above steps is the same as that of the previous section. The downside of this method is that if you abort your commit all your staged hunks are completely undone leaving you with only unstaged changes. While this is not really an issue in this example it can be quite a time waster in larger change sets.
The interactive patch mode offers more options than those I have demonstrated in this article. Besides the options that you have seen listed in the help that we did not explore here, you can for example also be presented with the s (split) option which allows you to split a hunk into smaller hunks (after which the rest of the process continues on in very much the same way) which may sometimes negate the need for you to use the edit option.