git: branching removed some commits
I had a weird situation today.. I'll try and recreate what I think happened.
I wanted to move a speculative change (made to a_file
) to a new branch and continue working on the main branch without it.
On master with a_file
and b_file
dirty I did:
git checkout -b saved_feature
git commit a_file -m "Putting this modification on a different branch"
git checkout master
At this point git complained that b_file was dirty - this was a warning sign but I didn't recognise it.
I was still on branch saved_feature
so I thought I could do:
git stash save
git checkout master
So far so good
git stash pop
At this point I get an error saying that the stash couldn't be merged.
I examine the log - for some reason there are about 6 days worth of commits that were originally committed to the master
branch but which were not in the log. These commits were only on the new branch that I had created (I checked in case I had been committing them to a different branch).
After examining the log of the saved_feature
branch, I can see that they are all there.
What happened?
I next tried on master
:
git merge saved_feature
But the fast forward option failed with a ton of conflicts.
I also开发者_开发问答 use git-svn to push changes to an external repository so on master
again I did:
git svn rebase
This recovered some of the previously pushed commits from svn.
I then cherry-picked the rest of the most recent commits from the saved_feature
branch,
I then did a git stash pop
, fixed the conflicts that should have been automatically merged, but were not, and finally had my master
in the state it was originally.
Could anyone point out in this sorry tale where my mental model and git parted ways & how I can avoid getting into messes such as these again?
You were probably working those last 6 days on a detached HEAD from an ancestor of master HEAD.
(thank you Chris Johnsen for suggesting that last part: it explains potentially everything)
Suppose you have:
x--x--x--x <- master
^
|
T1 (tag)
If you do a 'git checkout T1
' to see that T1
content, boom: detached HEAD right there.
If you do some fixes from T1
, you end up with
x--x--x--x <- master
^\
| -y--y--y--y--y--y <- detached HEAD (a dirty, b dirty)
|
T1(tag)
Now, a git checkout -b saved_feature
at this point would create a branch with the last 6 (days worth of) commits in it:
x--x--x--x <- master
^\
| -y--y--y--y--y--y--a <- saved_feature (a committed, b dirty)
|
T1(tag)
, but the checkout to master
is not trivial for file b
.
And a merge from master
to saved_feature
won't be trivial either (certainly not a fast-forward one)
Anyhow, that is why it is important to keep an eye at all time at the current branch you are actually working in.
精彩评论