Re: How to recover a lost commit...
- From
Jonathan Nieder <jrnieder@gmail.com>
- Date
- Nov 11, 2010, 17:58 UTC
- Message-ID
- <20101111175836.GD16972@burratino>
- In-Reply-To
- <AANLkTikqBXjAf44O0QERH39rK+7nNA8uD2CwtPKJTTyV@mail.gmail.com>
Patrick Doyle wrote:
Show 6 quoted lines
> Thank you for your reply and cogent explanation. Yes, in fact, I did > do a "git reset HEAD^". Somewhere along the way, I decided that was a > way to make my working copy look like it did prior to a commit. > > I thought that git reset only affected HEAD. I didn't realize that it > also affected the branch pointer.
Right. In general, git operations that update HEAD also tend to take the current branch along with them. So:
# update the current branch to include a new commit git commit
# update the current branch to include a change from another branch git cherry-pick --ff $rev
# update the current branch to incorporate the history of another branch git merge $rev
# reset the current branch head to match _that_ commit git reset --keep $rev
# only reset the current branch head; index and worktree will be untouched git reset --soft $rev
If you want to use such an operation without updating a certain branch, then switch to a different branch.
# switch branches: we are following 'topic' now git checkout topic
# detach from all branches: we are building unanchored history now git checkout HEAD^0
See the section DETACHED HEAD from the "git checkout" manual for details.
> Your "great power, great responsibility" comment will make me treat > "git reset" with a lot more fear and respect.
Once you're used to it, it is not so scary. If you pass paths to "git reset", it will not change HEAD; instead, it changes the content registered in the index:
git reset some-crazy-old-commit -- foo.c bar.c baz.c git diff --cached
If you do not pass paths, it will update HEAD to point to the specified commit.
# the last commit was bad; discard it git reset --keep HEAD^
# I'm totally lost. Let's just start over, based on the version
# that worked from yesterday.
git reset --hard @{yesterday}# specialized operation: the tracked content of all files should # be used as a single commit on top of some other revision git reset --soft $new_parent git commit
# less strange way to do about the same thing git reset $new_parent git diff; # looks good? git add -u git commit
If you do not pass paths and do not pass a revision arg, this means you wanted to update HEAD to point to the commit it is already at. In other words, with --soft or --keep this is basically a noop, with --hard it discards any changes in working-tree files you haven't committed, with no operation mode arg it makes the index match the HEAD commit.
> $ git merge --no-commit > $ git reset > > Why is that "git reset" benign, when the "git reset HEAD^" wasn't benign before?
There should be a revision argument after "git merge --no-commit".
This "git reset" is equivalent to "git reset HEAD": it resets the index to match the current commit, so the changes applied by the merge appear as local changes.
Regards, Jonathan