40 Retrieving “Lost” Commits

Rebasing commits causes the history of your repository to change. Ever wonder what happens if you accidentally delete the wrong commit in an interactive rebase? The commit—the point in the repository that recorded the change—is still stored in your repository, but it’s orphaned. You can use the reflog to find that commit, even though the normal Git log doesn’t show it.

The Git reflog tracks every time the tip of a branch changes. The tip is the commit that a particular branch points to. Back in Part III, Organizing Your Repository with Branches and Tags, we talked more about branches and how they are pointers to commits. Each time you commit a change to a branch, the branch is updated to point to that new commit, and the change is logged in the reflog.

During normal Git usage, you don’t need to concern yourself with the reflog. It’s handy for fixing mistakes, however.

For example, you run an interactive rebase (discussed in more detail in Task 28, Controlling How You Replay Commits) and a few days later realize that you accidentally removed the wrong commit during the rebase. Catching it right after the fact means you can use git reset ORIG_HEAD, but since you didn’t, your options are limited to one: using the reflog.

Running git reflog, you can find the commit before you ran your rebase and check it out directly. From there, you can determine the commit IDs for the missing commit, switch to your current branch, and cherry-pick the change back into your current branch.

Also available are the subcommands delete and expire, which delete specific reflog entries and expire entries beyond a certain point, respectively. Under most normal circumstances, you don’t need to use either.

Rewriting history is a powerful part of the Git toolkit. The reflog helps keep you from hurting yourself too much.

What To Do...
  • View the reflog.
     
    prompt>​ git reflog
  • Retrieve a lost commit.

    First, let’s “lose” a few commits:

     
    prompt>​ mkdir /work/tmp-repo && cd /work/tmp-repo
     
    prompt>​ git init
     
    Initialized empty Git repository in /work/tmp-repo/.git/
     
    ...​ add files a, b, c, d to the repository so we have some commits ...
     
    prompt>​ for i in a b c d
     
    do echo "simple $i" >> $i && git add $i && git commit -m "simple $i"
     
    done
     
    ...​ output from Git ...
     
    prompt>​ git rebase -i HEAD~2
     
    ...​ delete the "simple b" commit ...
     
    Successfully rebased and updated refs/heads/master.
     
    prompt>​ git log --oneline
     
    4325c46 simple c
     
    4b2a2ba simple a
     
    ...​ re-run the for loop above to add a few new commits ...

    You can see that you’ve deleted the =simple b commit. Now you can save it with git reflog:

     
    prompt>​ git reflog
     
    7ab141b HEAD@{0}: commit: simple e
     
    ...​ and so on, and so on ...
     
    4b2a2ba HEAD@{3}: checkout: moving from master to 4b2a2ba
     
    e563dcc HEAD@{4}: commit: simple c
     
    2b469ed HEAD@{5}: commit: simple b
     
    prompt>​ git cherry-pick 2b469ed
     
    Finished one cherry-pick.
     
    [master fcc3a79] simple b
     
    1 files changed, 1 insertions(+), 0 deletions(-)
     
    create mode 100644 b

Related Tasks

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.124.145