Reputation: 48589
I tried the suggestion here:
How to stage only part of a new file with git?
git add -N new_file git add -i
But I can't get it to work because the interactive mode presents the whole file without the s
choice, which would enable me to split the file into smaller parts, and thereby stage part of the file:
~/git_practice$ git init my_project
Initialized empty Git repository in /Users/7stud/git_practice/.git/
~/git_practice$ cd my_project
~/git_practice/my_project$ git status
On branch master
Initial commit
nothing to commit (create/copy files and use "git add" to track)
~/git_practice/my_project$ echo This is the README file. > README.txt
~/git_practice/my_project$ ls
README.txt
~/git_practice/my_project$ git status
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.txt
nothing added to commit but untracked files present (use "git add" to track)
~/git_practice/my_project$ git add README.txt
~/git_practice/my_project$ git commit -m "Add README file."
[master (root-commit) e815ed7] Add README file.
1 file changed, 1 insertion(+)
create mode 100644 README.txt
~/git_practice/my_project$ git status
On branch master
nothing to commit, working directory clean
~/git_practice/my_project$ git checkout -b new_feature
Switched to a new branch 'new_feature'
~/git_practice/my_project$ m new_feature.rb
(m is an alias I setup for the mvim command, which launches the macvim text editor.)
This is the code I entered in new_feature.rb:
def addition(x, y)
x+y
end
def substraction(x,y)
x-y
end
#Uh oh! I got carried away and created two new features.
#I want to split addition/subtraction into two commits.
Back at the command line:
~/git_practice/my_project$ git add -p new_feature.rb
No changes.
That didn't work. Instead, I had to do:
~/git_practice/my_project$ git add -N new_feature.rb
As far as I can tell, that essentially adds a blank version of new_feature.rb to the staging area; then you can patch that blank file with a portion of the code in new_feature.rb:
~/git_practice/my_project$ git add -i new_feature.rb
staged unstaged path
1: +0/-0 +10/-0 new_feature.rb
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
-i
stands for interactive. You are asking git to interactively prompt you with questions about how to add the file to the staging area. In response, git displays a menu with various choices. You can enter either the number preceding a choice or the first letter of a choice(e.g. p
for patch):
What now> p
staged unstaged path
1: +0/-0 +10/-0 new_feature.rb
There could be more than one file listed there, so you have to choose the number preceding the name of the file that you want to patch (The numbers under staged
indicate that the staged version of the file is blank, while the numbers under unstaged
indicate that the unstaged file has 10 new lines compared to the staged version):
Patch update>> 1
staged unstaged path
* 1: +0/-0 +10/-0 new_feature.rb
The asterisk indicates the file that you chose to patch. To actually begin the patch, you have to hit Return at the next prompt:
Patch update>> <Hit Return>
diff --git a/new_feature.rb b/new_feature.rb
index e69de29..b44829e 100644
--- a/new_feature.rb
+++ b/new_feature.rb
@@ -0,0 +1,10 @@
+def addition(x, y)
+ x+y
+end
+
+def substraction(x,y)
+ x-y
+end
+
+#Uh oh! I got carried away and created two new features.
+#I want to separate addition/subtraction into two commits.
Stage this hunk [y,n,q,a,d,/,e,?]?
According to the answer:
I need to choose the e
option, which presents this text:
# Manual hunk edit mode -- see bottom for a quick guide
@@ -0,0 +1,10 @@
+def addition(x, y)
+ x+y
+end
+
+def substraction(x,y)
+ x-y
+end
+
+#Uh oh! I got carried away and created two new features.
+#I want to separate addition/subtraction into two commits.
# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
#
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging. If it does not apply cleanly, you will be given
# an opportunity to edit again. If all lines of the hunk are removed,
# then the edit is aborted and the hunk is left unchanged.
~
~
"~/git_practice/my_project/.git/addp-hunk-edit.diff" 21L, 671C
Editing that file does not change the original file(new_feature.rb). The results of editing that file and saving it will be the portion of the file that gets staged, e.g. here is my edit:
# Manual hunk edit mode -- see bottom for a quick guide
@@ -0,0 +1,10 @@
+def addition(x, y)
+ x+y
+end
# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
#
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging. If it does not apply cleanly, you will be given
# an opportunity to edit again. If all lines of the hunk are removed,
# then the edit is aborted and the hunk is left unchanged.
~
~
"~/git_practice/my_project/.git/addp-hunk-edit.diff" 21L, 671C
Then after saving and quitting the text editor:
git commit -m "Add addition() method."
At this point, you can do a diff to compare what git committed v. what the original file looks like:
~/git_practice/my_project$ git diff new_feature.rb
diff --git a/new_feature.rb b/new_feature.rb
index 6579fef..b44829e 100644
--- a/new_feature.rb
+++ b/new_feature.rb
@@ -1,3 +1,10 @@
def addition(x, y)
x+y
end
+
+def substraction(x,y)
+ x-y
+end
+
+#Uh oh! I got carried away and created two new features.
+#I want to separate addition/subtraction into two commits.
A blank
at the start of the line means the line is common to the committed file and the original file. A +
at the start of the line means the line does not appear in the committed file, but the line appears in the original file. (And a -
sign at the beginning of a line means the line appears in the committed file but not the original file.) For more details on reading a diff, including what @@ -1,3 +1,10 @@
means, see here .
Then I repeated the process for the second method:
git add -p new_feature.rb
(That command is equivalent to git add -i new_feature.rb
and then choosing the patch menu item.)
After choosing e
, I only had to delete my comment at the end of the file:
+#Uh oh! I got carried away and created two new features.
+#I want to separate addition/subtraction into two commits.
Then another commit:
git commit -m "Add subtraction() method."
Then I was left with the original file containing the comment at the bottom, which I didn't want in the file. Additionally, the comment was causing new_feature.rb to show up in git status
as a modified file because the committed version didn't contain the comment. So, I reset the original file to what git knows:
git checkout new_feature.rb
That erases any differences between the committed file and the unstaged original file--and is unrecoverable.
That gave me a clean git status
:
$ git status
On branch new_feature
nothing to commit, working directory clean
And here is the commit history:
$ git log
commit 70c566157a0f41052c6091ce9025d8b95722015f
Author: 7stud <[email protected]>
Date: Tue May 26 13:06:21 2015 0000
Add subtraction() method.
commit 2ca5952c53bae7bc407d21cb3601395886d2cd4c
Author: 7stud <[email protected]>
Date: Tue May 26 13:05:41 2015 0000
Add addition() method.
commit 72ae28cbd1d7cf998eca5862b18e2af45b58f752
Author: 7stud <[email protected]>
Date: Tue May 26 13:00:55 2015 0000
Add README file.
Upvotes: 4
Views: 200
Reputation: 32681
There are no unchanged lines in your hunk, therefore you cannot split it up. Use the e
command and manually edit your diff. Using vim is especially helpful here for it's advanced line editing features.
It will look like this:
# Manual hunk edit mode -- see bottom for a quick guide
@@ -0,0 +1,10 @@
+def addition(x, y)
+ x+y
+end
+
+def substraction(x,y)
+ x-y
+end
+
+#Uh oh! I got carried away and created two new features.
+#I want to separate addition/subtraction into two commits.
# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
#
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging. If it does not apply cleanly, you will be given
# an opportunity to edit again. If all lines of the hunk are removed,
# then the edit is aborted and the hunk is left unchanged.
Upvotes: 3