[this is an answer to "How do I revert rm -rf .git/refs/heads
"]
You can restore your branches by reading the branch names and last active commit straight from the log files :
find .git/logs/refs/heads -type f | while read log; do
ref=$(echo $log | sed -e 's,logs/,,')
mkdir -p $(dirname $ref)
echo $(tail -1 $log | cut -d' ' -f2) > $ref
done
Run the above on a linux-ey system with bash
, or in git-bash
on Windows.
Step by step :
- git stores the evolution of each branch / reference in a file, under
.git/logs
. The first command lists those files for branches (refs starting with refs/heads
) :
$ find .git/logs/refs/heads -type f
.git/logs/refs/heads/master
.git/logs/refs/heads/foobar
.git/logs/refs/heads/baz/2
.git/logs/refs/heads/baz/1
You can look at the content of any of these files :
$ cat .git/logs/refs/heads/baz/2
0000000... 219145b... Legec <some@email.com> 1603086835 +0200 branch: Created from master
219145b... 425bc45... Legec <some@email.com> 1603086837 +0200 commit: d.txt
425bc45... 84324a8... Legec <some@email.com> 1603087374 +0200 commit: e.txt
84324a8... 5c2e4de... Legec <some@email.com> 1603087380 +0200 rebase (finish): refs/heads/baz/2 onto cbe105c...
each line stores "that ref moved from xxx to yyy", with a message describing what triggered this evolution (commit, rebase, reset ...)
This is the file from which git reflog that/branch
reads its info.
to get the path to the actual ref, you just need to ditch the logs/
part from this path :
ref=$(echo $log | sed -e 's,logs/,,')
suppose your branch is named thats/my/branch/name
, you need to recreate a directory at .git/refs/heads/thats/my/branch/
before creating file name
in it :
mkdir -p $(dirname $ref)
finally : from the last line of the log file (tail -1 $log
) extract the second field (cut -d ' ' -f2
) and store that in the approriate ref file :
echo $(tail -1 $log | cut -d' ' -f2) > $ref