1

I accidentally stopped an ongoing git commit and later when I try to

git commit -m"xyz" 

I get the following message

fatal: cannot lock ref 'HEAD': Unable to create 'G:/folder/.git/HEAD.lock': File exists.

Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes
are terminated then try again. If it still fails, a git process
may have crashed in this repository earlier:
remove the file manually to continue.

I tried following the suggestions given here Git cannot lock ref 'HEAD': unable to resolve reference HEAD and tried

 rm -rf .git/refs/heads/

Unfortunately, this didn't help and I still get the same error message posted above when I try git commit.

I also tried git reset and this also gives the same message displayed above.

Alternate suggestions on how to resolve this issue will be really helpful.

Ben W
  • 930
  • 6
  • 16
Natasha
  • 1,111
  • 5
  • 28
  • 66
  • 2
    Whoa, `rm -rf .git/refs/heads/` basically destroys your repository! If it did not, you either did not have any commits, or have just cloned the repository, or you have just completed a `git gc`. – j6t Oct 18 '20 at 14:32
  • @j6t I didn't clone the repo. May I know how to check if my repository isn't/is destroyed? – Natasha Oct 18 '20 at 14:36
  • Why not remove the lock file? – evolutionxbox Oct 18 '20 at 16:13
  • @evolutionxbox I tried rm -rf HEAD.lock in .git. Post this when I try again to commit , I see `741 files changed, 2764175 insertions(+), 3954 deletions(-)` . I definitely didn't make these many changes after what I had committed and pushed yesterday. I am not sure if this is because I did `git reset` a while ago. So is it safe to push my changes? – Natasha Oct 18 '20 at 16:36
  • What you see *may* be a result of that you blew away your branches with `rm -rf .git/refs/heads/`. You basically destroyed all your commits since you pushed the last time. In your current state, **do not push**, or **all** your commits are gone!! – j6t Oct 18 '20 at 17:15
  • Serious debugging is necessary to salvage as much of your work as possible. As a first step, make a backup copy of your working directory, including what you still have in the `.git` directory before you do any further experiments. At this point, consult an expert near you that looks over your shoulder. – j6t Oct 18 '20 at 17:19
  • 2
    There's still a trace of where the refs were (name and last active commit) under `.git/log` – LeGEC Oct 18 '20 at 17:53
  • I downvoted and left a comment on the answer that suggested `rm -rf .git/refs/heads` in the post OP linked. Not a great look. – Soren Bjornstad Oct 18 '20 at 20:56
  • 1
    @LeGEC: It's `.git/logs` with an *s*, at least on my machine. I got curious and tried whacking a repo this way myself, and `git reflog` doesn't work with the repository in this state, so good to know. – Soren Bjornstad Oct 18 '20 at 20:58
  • 1
    please define "stopped an ongoing commit". How? – Daemon Painter Oct 19 '20 at 09:22
  • 1
    @DaemonPainter I did a ctrl + C – Natasha Oct 19 '20 at 09:29

2 Answers2

2

[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
    
LeGEC
  • 46,477
  • 5
  • 57
  • 104
0

Simply navigate to your local repository in the cloned directory and look for .git folder, indise .git you will see the lock file. JUST DELETE it. and you are done.