Home >Web Front-end >CSS Tutorial >Using the Reflog to Restore Lost Commits
This article is part of the "Advanced Git" series. Be sure to follow us on Twitter or sign up for our newsletter to get a look at future articles!
Git's "Reflog" feature is little known, but it's very practical. Some people call it a "safety net" and I prefer to think of it as a "diary" of Git. This is because Git uses it to record every move of the HEAD pointer (i.e., every commit, merge, rebase, pick, reset, etc.). Git logs your actions in Reflog, making it a valuable logbook and a good starting point when problems arise.
In the last part of this "Advanced Git" series, I will explain the difference between git log
and git reflog
and show you how to use Reflog to recover deleted commits and deleted branches.
git log
or git reflog
: What's the difference? In previous posts, I suggested that you use the git log
command to check previous events and view your commit history, which is exactly what it does. It displays the current HEAD and its ancestors, i.e. its parent, next parent, and so on. The logs trace back to the beginning of the commit history by recursively printing the parent of each commit. It is part of the repository, which means it will be copied after you push, fetch, or pull.
On the other hand, git reflog
is a private workspace-related record. It does not iterate over the ancestor list. Instead, it displays an ordered list of all commits pointed to by HEAD in the past. That's why you can think of it as some sort of "undo history" like you see in word processors, text editors, etc.
This local record is not technically part of the repository and it is stored separately from the commit. Reflog is a file in .git/logs/refs/heads/
which tracks the local commits of each branch. Git's diaries are usually cleaned after 90 days (this is the default), but you can easily adjust the expiration date of the Reflog. To change the number of days to 180, just type the following command:
$ git config gc.reflogExpire 180.days.ago
Alternatively, you can decide that your Reflog will never expire:
$ git config gc.reflogExpire never
Tip: Remember that Git distinguishes the repository's configuration files ( .git/config
), global user configuration ( $HOME/.gitconfig
), and system-wide settings ( /etc/gitconfig
). To adjust the user or system's Reflog expiration date, add --system
or --global
parameter to the command shown above.
Enough theoretical background – let me show you how to use git reflog
to correct errors.
Imagine the following scenario: After viewing the commit history, you decide to delete the last two commits. You bravely executed git reset
, and the two commits disappeared from the commit history...After a while you noticed that this was a bug. You just lost your valuable changes and started panic!
Do you really have to start from scratch? No need. In other words: stay calm and use git reflog
!
So let's mess things up and make this mistake in real life. The next image shows our original commit history in Tower (a graphical Git client):
We want to delete the two commits and set the Change About and Imprint Title commit (ID: 2b504bee) as the last revision on our master branch. We just copy the hash ID to the clipboard, then use git reset
in the command line and enter that hash value:
$ git reset --hard 2b504bee
Look! The submission disappeared. Now, let's assume this is an error and look at the Reflog to recover the lost data. Type git reflog
to view the journal in your terminal:
You will notice that all entries are arranged in chronological order. This means: The latest commit is at the top. And, if you look closely, you'll notice the deadly git reset
operation at the top a few minutes ago.
The diary seems to work – that’s good news. So let's use it to undo the last action and restore the state before the reset command. Like before, copy the hash ID (e5b19e4 in this particular example) to the clipboard. You can use git reset
again, which works perfectly. But in this case I'll create a new branch based on the old state:
$ git branch happy-ending e5b19e4
Let's take a look at our graphical Git client again:
As you can see, a new branch called happy-ending has been created with our previously deleted commits – great, nothing is lost!
Let's look at another example and use Reflog to restore the entire branch.
The next example is similar to our first scenario: we will delete something—this time the entire branch. Maybe your client or team leader tells you to delete a feature branch, maybe it's the idea of cleaning up yourself. Worse, a commit (C3 in the picture) is not included in any other branch, so you are definitely losing data:
Let's actually do this and then restore the branch later:
You need to leave it before you can delete feature/login
branch. (As shown in the screenshot, it is the current HEAD branch, you cannot delete the HEAD branch in Git.) So we will switch the branch (to master) and then we will delete feature/login
:
OK… Now let’s assume that our client or team leader has changed his mind. After all, feature/login
branches (including their commits) are required. What should we do?
Let's take a look at Git's diary:
$ git reflog 776f8ca (HEAD -> master) HEAD@{0}: checkout: moving from feature/login to master b1c249b (feature/login) HEAD@{1}: checkout: moving from master to feature/login [...]
We have proved to be lucky again. The last entry shows how we switch from feature/login
to master. Let's try to return to the previous state and copy the hash ID b1c249b to the clipboard. Next, we will create a branch named feature/login
based on the required state:
$ git branch feature/login b1c249b $ git branch -vv feature/login b1c249b Change Iprint page title * master 776f8ca Change about title and delete error page
Great – the branch recovers from death, and also includes valuable commits we consider lost:
If you use Git in a desktop GUI like Tower, you can undo your last action just by pressing CMD Z just like a text editor or word processor when you type in an error.
Git's Reflog can be a real savior! As you can see, it's very easy to remove missing commits from the grave or even the entire branch. All you need to do is find the correct hash ID in the Reflog - the rest is a piece of cake.
If you want to dig into advanced Git tools, feel free to check out my (free!) Advanced Git Toolkit: It is a collection of short videos on topics such as branching strategies, interactive rebases, Reflogs, submodules, and more.
This is the last part of our "Advanced Git" series on CSS-Tricks. I hope you enjoyed these articles. Happy hacker!
The above is the detailed content of Using the Reflog to Restore Lost Commits. For more information, please follow other related articles on the PHP Chinese website!