Here's an example of restoring orphaned commits in a local repository using
git reflog.
First, let's create a test repository, add some data to it, wipe out some data leaving an orphaned commit, and then restore it on a new branch using
git reflog.
Creating some data:
git init
echo "Initial File" > file.txt
git add .
git commit -m "Add initial file"
echo "@41.7266831,-81.2882074,13z 12345" > file.txt
git commit -am "Cat walked across my keyboard, oops, sorry"
Unfortunately, during work, a cat walked across the keyboard, making a random series of changes, which went unnoticed and were rolled into a commit.
Let's take a quick look at the current project history:
git log -p
commit f3fa43be38be2988b35b25336d84735a8bcd611c (HEAD -> master)
Author: Hooman <Hooman>
Date: Wed Mar 20 17:57:04 2019 +0700
Cat walked across my keyboard, oops, sorry
diff --git a/file.txt b/file.txt
index f1ec229..50ad6e0 100644
--- a/file.txt
+++ b/file.txt
@@ -1 +1 @@
-Initial File
+@41.7266831,-81.2882074,13z 12345
commit 6ba95e9ee8b289b19ca31bd4ee062fb31d372efc
Author: Hooman <Hooman>
Date: Wed Mar 20 17:57:04 2019 +0700
Add initial file
diff --git a/file.txt b/file.txt
new file mode 100644
index 0000000..f1ec229
--- /dev/null
+++ b/file.txt
@@ -0,0 +1 @@
+Initial File
Realizing the mistake, the programmer quickly removed the commit, and reset the master branch to the commit before, leaving no trace of the accidental changes on master.
The history of the project is now:
git log -p
commit 6ba95e9ee8b289b19ca31bd4ee062fb31d372efc (HEAD -> master)
Author: Hooman <Hooman>
Date: Wed Mar 20 17:57:04 2019 +0700
Add initial file
diff --git a/file.txt b/file.txt
new file mode 100644
index 0000000..f1ec229
--- /dev/null
+++ b/file.txt
@@ -0,0 +1 @@
+Initial File
But things are not as they seem. That commit was no cat accident! No, the programmer was actually an evil mastermind, with a penchant for stroking feline friends. He has in reality embezzled meeeelions of dollars from the company, and used half the money to buy nuclear weapons to hold the world hostage. The accidental addition was actually an encoded message with the coordinates and combination to a safe containing the other half of the embezzled money, and the nuclear launch codes. We need to get that information back.
Fortunately, Git tracks all moves to the current
HEAD. Each time you switch branches, or make a commit, you update the position of
HEAD. The previous location of
HEAD is stored in the
git reflog. You can use the syntax
HEAD@{n} to access what
HEAD was
n moves ago. We check the reflog with:
git reflog
6ba95e9 (HEAD -> master) HEAD@{0}: reset: moving to HEAD^
f3fa43b HEAD@{1}: commit: Cat walked across my keyboard, oops, sorry
6ba95e9 (HEAD -> master) HEAD@{2}: commit (initial): Add initial file
Aha, the commit with the secret message is plainesly (typo?) visible.
We restore the deleted commit to a new branch as follows:
git checkout HEAD@{1}
git checkout -b newBranchWithRestoredCommit
At this point, we can pause and check the current state of the repository:
git branch --all
master
* newBranchWithRestoredCommit
The history of
newBranchWithRestoredCommit:
git log -p
commit f3fa43be38be2988b35b25336d84735a8bcd611c (HEAD -> newBranchWithRestoredCommit)
Author: Hooman <Hooman>
Date: Wed Mar 20 17:57:04 2019 +0700
Cat walked across my keyboard, oops, sorry
diff --git a/file.txt b/file.txt
index f1ec229..50ad6e0 100644
--- a/file.txt
+++ b/file.txt
@@ -1 +1 @@
-Initial File
+@41.7266831,-81.2882074,13z 12345
commit 6ba95e9ee8b289b19ca31bd4ee062fb31d372efc (master)
Author: Hooman <Hooman>
Date: Wed Mar 20 17:57:04 2019 +0700
Add initial file
diff --git a/file.txt b/file.txt
new file mode 100644
index 0000000..f1ec229
--- /dev/null
+++ b/file.txt
@@ -0,0 +1 @@
+Initial File
The history of
master:
git log -p master
commit 6ba95e9ee8b289b19ca31bd4ee062fb31d372efc (master)
Author: Hooman <Hooman>
Date: Wed Mar 20 17:57:04 2019 +0700
Add initial file
diff --git a/file.txt b/file.txt
new file mode 100644
index 0000000..f1ec229
--- /dev/null
+++ b/file.txt
@@ -0,0 +1 @@
+Initial File
And for good measure, since we were just creating and switching branches, here's what the current reflog now looks like:
git reflog
f3fa43b (HEAD -> newBranchWithRestoredCommit) HEAD@{0}: checkout: moving from f3fa43be38be2988b35b25336d84735a8bcd611c to newBranchWithRestoredCommit
f3fa43b (HEAD -> newBranchWithRestoredCommit) HEAD@{1}: checkout: moving from master to HEAD@{1}
6ba95e9 (master) HEAD@{2}: reset: moving to HEAD^
f3fa43b (HEAD -> newBranchWithRestoredCommit) HEAD@{3}: commit: Cat walked across my keyboard, oops, sorry
6ba95e9 (master) HEAD@{4}: commit (initial): Add initial file