Git commit --amend merged two commits
Solution 1
If you have staged files and do
git commit --amend
You will create a new commit with everything in the previous commit plus everything staged and this new commit will replace the previous commit as the tip of the branch you have checked out.
git commit --amend
without any staged files can be used to change commit message but notice that even in the case where you have no staged files you will get a new sha1, in other words a new commit.
From the documentation:
Used to amend the tip of the current branch. Prepare the tree object you would want to replace the latest commit as usual (this includes the usual -i/-o and explicit paths), and the commit log editor is seeded with the commit message from the tip of the current branch. The commit you create replaces the current tip — if it was a merge, it will have the parents of the current tip as parents — so the current top commit is discarded.
Solution 2
This is expected behaviour. From the git commit
documentation.
--amend
Replace the tip of the current branch by creating a new commit. The recorded tree is prepared as usual (including the effect of the
-i
and-o
options and explicit pathspec), and the message from the original commit is used as the starting point, instead of an empty message, when no other message is specified from the command line via options such as-m
,-F
,-c
, etc. The new commit has the same parents and author as the current one (the--reset-author
option can countermand this).It is a rough equivalent for:
$ git reset --soft HEAD^ $ ... do something else to come up with the right tree ... $ git commit -c ORIG_HEAD
but can be used to amend a merge commit.
You should understand the implications of rewriting history if you amend a commit that has already been published. (See the "RECOVERING FROM UPSTREAM REBASE" section in git-rebase[1].)
The important part to understand is git reset --soft HEAD^
. This will "remove" the commit from your history but won't change your working tree or index.
Take a look at the documentation of git reset
. Emphasis mine.
--soft
Does not touch the index file or the working tree at all (but resets the head to , just like all modes do). This leaves all your changed files "Changes to be committed", as git status would put it.
Solution 3
git commit --amend
will add staged changes to the most recent commit. Since it merged your two I would suspect that there was not two commits but one.
The man page explains this:
--amend
Replace the tip of the current branch by creating a new commit. The
recorded tree is prepared as usual (including the effect of the -i and
-o options and explicit pathspec), and the message from the original
commit is used as the starting point, instead of an empty message, when
no other message is specified from the command line via options such as
-m, -F, -c, etc. The new commit has the same parents and author as the
current one (the --reset-author option can countermand this).
It is a rough equivalent for:
$ git reset --soft HEAD^
$ ... do something else to come up with the right tree ...
$ git commit -c ORIG_HEAD
but can be used to amend a merge commit.
You should understand the implications of rewriting history if you
amend a commit that has already been published. (See the "RECOVERING
FROM UPSTREAM REBASE" section in git-rebase[1].)
Because you described working on more than one commit I'll explain how the above describe workflow could have gone instead:
A--B (origin/dev) (dev)
Edit files, and add staging (git add -u
) then:
$ git commit # edit a good message (see below)
A--B (origin/dev)
\
C (dev)
Now repeat:
$ git commit # edit another awesome message (see below)
A--B (origin/dev)
\
C--D (dev)
But now you realize commit C has a bad commit message. So we do a rebase:
$ git rebase -i origin/dev
In the editor you'll see commits C and D with their subject lines and a keyword pick
. Find the commit you want to fix and change the pick
to reword
then save the file.
git will open another editor and let you fix the commit message. Save and continue.
A note about commit messages (because I am trying to spread the word):
https://thoughtbot.com/blog/5-useful-tips-for-a-better-commit-message
Capitalized, short (50 chars or less) summary
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body. The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.
Write your commit message in the imperative: "Fix bug" and not "Fixed bug"
or "Fixes bug." This convention matches up with commit messages generated
by commands like git merge and git revert.
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Typically a hyphen or asterisk is used for the bullet, followed by a
single space, with blank lines in between, but conventions vary here
- Use a hanging indent
Comments
-
shkschneider almost 2 years
I have a remote 'dev' branch and was working on it locally.
I made a first commit on 'dev' with a commit message "my_feature", putting my local branch ahead of the remote by 1 commit.
I then developed some new stuff and made a
git add -u
, getting ready to commit. I then realized I wanted to rework the previous commit message as "my_feature (1/2)" to make my current commit message as "my_feature (2/2)", putting my local branch ahead of the remote by 2 commits.So I made a
git commit --amend
(thinking it would only edit the previous commit's message), edited the "my_feature" commit message as "my_feature (1/2)" and... ended up with a single commit labelled "my_feature (1/2)" having all my changes (first commit + staging files diffs) -- my index is now clean.So if I got it right, my command actually did a commit, also committed the staging files, which produced a single (merged?) commit?
I was not expecting Git to do such a thing. I just wanted to edit my old commit message, not to merge the old one with my current staging files. (Now that I think about it a
rebase
could have been better.)While I can understand why
git commit --amend
could commit (even if I only wanted to edit a commit message), I have problems to understand how Git merged my two commits into one with acommit
command.Anyone could clarify this to me?
$ git --version git version 1.7.10.4