Reputation: 24015
My current git status
looks like this:
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: docs/file3.org
# modified: src/main/R/lib.R
#
# 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: docs/file3.org
# modified: src/main/R/lib.R
I'd like to commit the staged changes to docs/file3.org
first, then the other staged changes. But if I do git commit -m '...' docs/file3.org
, it will commit both the staged & unstaged changes to that file.
Is there an easy way to do this? Or do I need to stash
my unstaged changes, unstage one of the files, commit the other, restage, commit, and stash pop
?
Upvotes: 20
Views: 21000
Reputation: 560
What's really weird, is that git-scm book explains staging exactly how you described:
unstaged changes of the same file don't go with commit, only staged changes.
Check it out: http://git-scm.com/book/en/Git-Basics-Recording-Changes-to-the-Repository#Staging-Modified-Files
I started testing and regardless of what changes of the same file I had staged, all changes went with the commit.
Upvotes: 5
Reputation: 26207
Since you only need to commit the staged changes to a file, you can just stash, keeping the indexed changes intact, and committing the file after that.
git stash --keep-index #Note that the staged changes also become part of the stash
git commit -m "Commit only one file" docs/file3.org
git commit -m "Commit other staged changed"
git stash pop
# This may raise CONFLICTS since the stash includes the earlier staged changes.
# In case of conflict, the stash is not popped, so you need to drop it explicitly.
Upvotes: 15
Reputation: 76115
I'm going to assume you're on master
for all this...
git branch whatever
git commit # commit currently staged changes as 'commit1'
git add docs/file3.org
git commit # commit unstaged changes as 'commit2'
You'll now have this
master
\
\--commit1--commit2
Now, run git log
and record the SHAs for 'commit1' and 'commit2'.
git checkout master
git cherry-pick commit2SHA
git cherry-pick commit1SHA
Which will give you
master--newcommit2--newcommit1
\
\--commit1--commit2
And then you can destroy the 'whatever' branch
git branch -D whatever
edit:
You could also do something similar using the stash:
git stash --keep-index # Save unstaged changes
git stash # Save staged changes
git stash pop stash@{1} # Pop unstanged changes
git commit ... # Commit unstanged changes
git stash pop stash@{0} # Pop staged changes
git commit ... # Commit staged changes
Upvotes: 2
Reputation: 1329822
git stash
is the best option, combined with.
git add --interactive
This should allow you to 'revert' (unstage) some files already added to the index.
Then git stash
would allow you to save those files and restore them.
(See "git add --patch
and --interactive
" article for an example)
Upvotes: 1