Sometimes you change the code and then you realize you would like to commit it as several separate patches. For example you fixed two bugs at once but then you decided you want to have the commits separated into two logical units – first bug fix and second bug fix.
As long as the changes don’t involve the same file, it’s easy to do. You just git add first file, commit, git add second file, commit. But what will you do if the two changes involved the same file?
There is a simple solution: git add --patch
Let’s see an example. I have made two changes in my README file – deleted one line and added one line. I want to stage it as two separate patches.
$ git add --patch README
diff --git a/README b/README
index 05ad773..2768fc1 100644
--- a/README
+++ b/README
@@ -1,4 +1,3 @@
-Welcome to autoqa!
Everything here is under heavy development so don't expect anything to
stay stable - modules, APIs, whatever. If it's expected to stay stable we
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? y
@@ -8,6 +7,7 @@ but if you have questions please feel free to contact us.
== Architecture ==
There's four main things in this tree: 'autoqa', 'events', 'watchers', and 'tests'.
+foo!
'autoqa' is the main binary that kicks off tests (using the autotest framework -
see http://autotest.kernel.org/ for details). It's typically supposed to be
Stage this hunk [y,n,q,a,d,/,K,g,e,?]? n
Git detects “hunks” (changed sections) in the file and asks for every hunk whether you want to stage it or not (see the prompt “Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]?“) . You can see that I staged the first hunk, and I didn’t staged the second one. (For explanation of the all the letters in the prompts type in the question mark.).
Now I see something like this:
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: README
#
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: README
#
Some parts of README were staged, some parts were not. I can display the difference between my HEAD and the staging area:
$ git diff --staged
diff --git a/README b/README
index 05ad773..bbc5249 100644
--- a/README
+++ b/README
@@ -1,4 +1,3 @@
-Welcome to autoqa!
Everything here is under heavy development so don't expect anything to
stay stable - modules, APIs, whatever. If it's expected to stay stable we
You can see that only one changed (the deleted line) is part of my staging area. Now I can commit and only this change will be part of it. Then I’ll stage the remaining changes in README and commit again. I’ve just easily split two changes in one file into two different commits. Voila!
Interactive mode
You can do the same way through interactive mode if you prefer:
$ git add --interactive
staged unstaged path
1: unchanged +1/-1 README
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now>
You are presented with the list of changed files and you can do different operations on them. Don’t forget to press h or 8 in this step. Action patch or 5 is exactly the same we saw with git add --patch
. After you select which file to work on (and press Enter once more), you select all the desired hunks:
What now> p
staged unstaged path
1: unchanged +1/-1 README
Patch update>> 1
staged unstaged path
* 1: unchanged +1/-1 README
Patch update>>
diff --git a/README b/README
index 05ad773..2768fc1 100644
--- a/README
+++ b/README
@@ -1,4 +1,3 @@
-Welcome to autoqa!
Everything here is under heavy development so don't expect anything to
stay stable - modules, APIs, whatever. If it's expected to stay stable we
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? y
@@ -8,6 +7,7 @@ but if you have questions please feel free to contact us.
== Architecture ==
There's four main things in this tree: 'autoqa', 'events', 'watchers', and 'tests'.
+foo!
'autoqa' is the main binary that kicks off tests (using the autotest framework -
see http://autotest.kernel.org/ for details). It's typically supposed to be
Stage this hunk [y,n,q,a,d,/,K,g,e,?]? n
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now>
Now I can display the status:
What now> s
staged unstaged path
1: +0/-1 +1/-0 README
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now>
In the README file I have 0 lines added and 1 line removed in the staging area, and one line added and zero lines removed in the unstaged area.
I can easily display the diff between HEAD and the staging area:
What now> d
staged unstaged path
1: +0/-1 +1/-0 README
Review diff>> 1
diff --git a/README b/README
index 05ad773..bbc5249 100644
--- a/README
+++ b/README
@@ -1,4 +1,3 @@
-Welcome to autoqa!
Everything here is under heavy development so don't expect anything to
stay stable - modules, APIs, whatever. If it's expected to stay stable we
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now>
That’s exactly what I want. Now I can just quit the interactive mode and commit.
The first approach (non-interactive) seems faster to me, but interactive mode can be also appealing for some people.
Enjoy!
