Git Partial Staging

It happens quite often to me that I have changed multiple places in a file but want to commit one of them only. An example would be package.json file in a Node.js project, which contains different parts: the project info and version, the predefined commands, the dependencies, and even the linter rules. One would want to commit the changes in the dependencies, but not in the predefined commands.

Introducing Interactive Staging

Let's assume you have two sets of changes in the package.json file. Let's take a look at them:

git diff package.json

The output is something like the following:

diff --git a/package.json b/package.json 
index 465ef44..ee478bb 100644 
--- a/package.json 
+++ b/package.json 
@@ -1,6 +1,6 @@ 
 { 
   "name": "@rxjsx/rxjsx", 
-  "version": "1.0.0", 
+  "version": "1.0.1", 
   "description": "RxJS Extensions", 
   "main": "lib/index.js", 
   "types": "lib/index.d.ts", 
@@ -38,7 +38,7 @@ 
     "jest": "^26.6.3", 
     "jest-junit": "^13.0.0", 
     "prettier": "^2.2.1", 
-    "rxjs": "^7.5.5", 
+    "rxjs": "^7.5.6", 
     "ts-jest": "^26.5.6", 
     "typescript": "^4.2.4" 
   }

So, we have a change in the version at the beginning of the file and another one in the dependencies in the middle. We want to stage the dependency change, but not the version change yet. To do so, we use the interactive add:

git add -i

The following text is printed out in the terminal:

staged     unstaged path 
  1:    unchanged        +9/-9 package-lock.json 
  2:    unchanged        +2/-2 package.json 
 
*** Commands *** 
  1: status       2: update       3: revert       4: add untracked 
  5: patch        6: diff         7: quit         8: help 
What now>

It shows that there are changes in package-lock.json and package.json. The available commands are listed down there. Let's type in p for patch and press enter:

What now> p
staged     unstaged path
1:    unchanged        +9/-9 package-lock.json
2:    unchanged        +2/-2 package.json
Patch update>>

Type in 2 meaning that we want to do partial staging on package.json:

Patch update>> 2  
           staged     unstaged path 
  1:    unchanged        +9/-9 package-lock.json 
* 2:    unchanged        +2/-2 package.json 
Patch update>>

Press enter meaning that that was all and we are finished here:

Patch update>>  
diff --git a/package.json b/package.json 
index 465ef44..ee478bb 100644 
--- a/package.json 
+++ b/package.json 
@@ -1,6 +1,6 @@ 
 { 
   "name": "@rxjsx/rxjsx", 
-  "version": "1.0.0", 
+  "version": "1.0.1", 
   "description": "RxJS Extensions", 
   "main": "lib/index.js", 
   "types": "lib/index.d.ts", 
(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? n

It now shows the first "hunk" of changes and asks what to do with it. We don't want to stage it, so we enter n:

@@ -38,7 +38,7 @@ 
     "jest": "^26.6.3", 
     "jest-junit": "^13.0.0", 
     "prettier": "^2.2.1", 
-    "rxjs": "^7.5.5", 
+    "rxjs": "^7.5.6", 
     "ts-jest": "^26.5.6", 
     "typescript": "^4.2.4" 
   } 
(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,?]? y

Now it shows the second hunk and we can enter y here. By doing that, the partial staging will finish and the interactive staging returns to the commands:

*** Commands *** 
  1: status       2: update       3: revert       4: add untracked 
  5: patch        6: diff         7: quit         8: help 
What now> q

Let's quit by entering q and pressing enter. Then do a git status:

git status

The output is as follows:

On branch master 
Your branch is up to date with 'origin/master'. 
 
Changes to be committed: 
  (use "git restore --staged <file>..." to unstage) 
        modified:   package.json 
 
Changes not staged for commit: 
  (use "git add <file>..." to update what will be committed) 
  (use "git restore <file>..." to discard changes in working directory) 
        modified:   package-lock.json 
        modified:   package.json

The file package.json is shown both as staged and not staged. That's because it's partially staged and some parts are not staged for the commit. You can go ahead and commit the changes.

Final Words

I write regularly on git, Docker, and DevOps.

  • Subscribe using the form on the page to get updates on Git and my Docker Security book.
  • Subscribe to my LinkedIn newsletter.
  • Subscribe to my Medium articles to get notified when I post something there.
  • Follow me on Twitter for Docker and git tips and also updates on my articles.

Other Posts in the Series

Post thumbnail
A guide to basic Git commands, including setting up your name and email, cloning a repository, checking the status of files, and committing changes.
Issue: #9
Series: Git Weekly
Beginner
Published: 5/30/2022