Git Logo Git Logo from https://git-scm.com/downloads/logos

As a developer, I don’t find it natural for me to do just one thing to my code base between commits. I end up cleaning up a couple things as I’m working on a new feature or bug ticket or even lump together two tickets that touch the same module. To this end, some of my commits ended up looking like this:

git add .
git commit -m "Fixed stuff not really sure of everything but whatever"

Eventually, I (or even worse someone else) would try to figure out what happened in that commit and have no idea because of the shitty commit message. That all changed the day I learned about git add -p.

Git add -p is the “interactive add” feature in Git so instead of adding an entire file I can just add a single changed section or several sections from a file.

As an example, I have the diff below. The original intention was to add the getVariable()/setVariable() functions but in working on that change I realized I misspelled “Something”. I could commit these in a single commit but then the reasoning might get lost (just imagine it’s a more complicated change :-) ).

Scotts-MacBook-Air:demo scottkeckwarren$ git diff
diff --git a/test.php b/test.php
index 8dbc750..9cbc00a 100644
--- a/test.php
+++ b/test.php
@@ -2,7 +2,7 @@
 
 namespace TPT\Demo;
 
-class Somethng
+class Something
 {
     private $variable = null;
 
@@ -10,4 +10,16 @@ class Somethng
     {
         $this->variable = 'New Value';
     }
-}
\ No newline at end of file
+
+    public function setVariable($value)
+    {
+        $this->variable = $value;
+
+        return $this;
+    }
+
+    public function getVariable()
+    {
+        return $this->variable;
+    }
+}

To do this I’m going to use git add -p start the interactive add:

Scotts-MacBook-Air:demo scottkeckwarren$ git add -p
diff --git a/test.php b/test.php
index 8dbc750..9cbc00a 100644
--- a/test.php
+++ b/test.php
@@ -2,7 +2,7 @@
 
 namespace TPT\Demo;
 
-class Somethng
+class Something
 {
     private $variable = null;
 
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? 

Git then shows me the first hunk I have to make a decision on. The options below are not all self explanitory so you can press ? to display more information:

Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? ?
y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk or any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk or any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help


namespace TPT\Demo;
 
-class Somethng
+class Something
 {
     private $variable = null;
 
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]?

In this case I’m going to press “y” because I do want to stage this hunk.

namespace TPT\Demo;
 
-class Somethng
+class Something
 {
     private $variable = null;
 
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? y

Then it’s going to display the next hunk which I will say no to:

@@ -10,4 +10,16 @@ class Somethng
     {
         $this->variable = 'New Value';
     }
-}
\ No newline at end of file
+
+    public function setVariable($value)
+    {
+        $this->variable = $value;
+
+        return $this;
+    }
+
+    public function getVariable()
+    {
+        return $this->variable;
+    }
+}
Stage this hunk [y,n,q,a,d,/,K,g,e,?]? n

After this, I can do a quick git status to make sure everything makes sense. In this case we see something interesting which is the fact that test.php is both staged and not staged because we’re only committing part of the file.

Scotts-MacBook-Air:demo scottkeckwarren$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   test.php

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:   test.php

Finally I can commit the change with a useful commit message.

Scotts-MacBook-Air:demo scottkeckwarren$ git commit -m "Renamed Somethng to Something"
[master a139eab] Renamed Somethng to Something
 1 file changed, 1 insertion(+), 1 deletion(-)

Then I can commit the remainder of the change.

Scotts-MacBook-Air:demo scottkeckwarren$ git commit -a -m "Added getter and setter functions for variable"
[master c334d29] Added getter and setter functions for variable
 1 file changed, 13 insertions(+), 1 deletion(-)
Scotts-MacBook-Air:demo scottkeckwarren$