About restoring a deleted Git branch


Recently, a branch was deleted from the server without it being merged.
Luckily for us, we had a local copy.

We used used the command git reflog to get access to the reference logs of the branch.
The command returned results similar to the below:

271f0084 [email protected]{0}: pull: Merge made by the 'recursive' strategy.
 0e71c0b [email protected]{1}: commit: Minor change: Cracked NSA systems
 c81624b [email protected]{2}: pull: Fast-forward
 ef1f281 [email protected]{3}: commit (amend): Deployed satelite
 1ed1a5a [email protected]{4}: commit (amend): Deployed satelite
 a8682cb [email protected]{5}: commit (amend): Deployed satelite
 e4560c8 [email protected]{6}: commit (amend): Deployed satelite
 1679a90 [email protected]{7}: commit (amend): Deployed satelite
 d27d2c9 [email protected]{8}: commit: Deployed satelite
 aaf8261 [email protected]{9}: checkout: moving from master to crack-nsa-systems
 2500e11 HE[email protected]{10}: clone: from ssh://[email protected]:7999/secret/bananas.git

From this information we got the hash value in front of the commit which we wanted to use to restore, which was 271f0084.

Then, we checked out that version using

git checkout 271f0084;

When we tried to push the branch back to the server the Git pre commit hooks blocked the operation.
Based on the rsa key used, we could only submit changes that were committed by the owner of that key.
The option to disable temporarily the pre commit hooks was unfortunately out of the question.
So we had to replace all author names and emails with the name of the one holding the key.

To do so we used the following command before pushing to the server once more:

git filter-branch --commit-filter '
   if [ "$GIT_COMMITTER_NAME" = "Doe, John" ];
   then
     GIT_COMMITTER_NAME="Squarepants, Bob";
     GIT_AUTHOR_NAME="Squarepants, Bob";
     GIT_COMMITTER_EMAIL="[email protected]";
     GIT_AUTHOR_EMAIL="[email protected]";
     git commit-tree "[email protected]";
   else
     git commit-tree "[email protected]";
   fi' HEAD

git filter-branch lets you rewrite Git revision history by rewriting the branches mentioned, in our case it was HEAD, applying custom filters on each revision. Those filters can modify each tree (e.g. removing a file or running a perl rewrite on all files) or information about each commit. Otherwise, all information (including original commit times or merge information) will be preserved.

HEAD is a reference to the currently checked out commit. In normal states, it’s actually a symbolic reference to the branch you have checked out.
Looking at the contents of .git/HEAD you’ll see something similar to ref: refs/heads/master.
The branch itself is a reference to the commit at the tip of the branch.

This post is also available in: Greek

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.