[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 withrefs/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- namein 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