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.