Git Stories — Chapter 1: “Already exists”
As a software engineer, one major thing I need to use is a Version Control System. And as you have guessed(as seen in the heading), my favorite VCS is the awesome Git! If you are not familiar with Git, try to learn it. It’s simply amazing. The rest of this article is for those who use Git. So if you don’t use Git or will never use, feel free to skip this article.
A few days back, we ended up in a very interesting situation while creating a branch out of a branch when we ran the Git command,
git checkout -b something/something_else/something_interesting
and it gave an error saying
error: ‘refs/heads/something/something_else’ exists; cannot create ‘refs/heads/something/something_else/something_interesting’
fatal: Failed to lock ref for update: Not a directory
And, yes obviously, we were confused because there was no branch named something/something_else/something_interesting in that repository. We created the branch out of the branch something/something_else, which was existing. This kind of confused me as why it was saying “exists” about our base branch and says cannot create a new branch. The branch names are completely different. Why is this happening? Interesting!
Then I tried to see what was in the directory refs/heads/, that was mentioned in the error.
The refs directory
I decided to dissect and study this. For those who are not so familiar with Git, your local repository has a directory named “.git” (like, dot-git where . (dot) is used in Linux for the hidden directories. So, this directory stores all the details about your repository. It’s the metadata, in other words. So our directory of interest is in this directory.
I started by listing files in “.git/refs/heads/” (ls .git/refs/heads/). I knew this stores the HEAD of your branch. Like the commit HEAD points to, currently. But never wandered into the internals. I found a directory called something inside that directory. Inside that, I found a file called something_else that holds a hash. I just checked and that’s the commit that HEAD of something/something_else and I realized suddenly how this works!
I realized how Git branches are not stored as strings but as files and directory structure. Yes! Interesting, right. This is just like how files and directories are stored in Linux. In a directory if you have a file called “something” you can’t create a directory called “something” in the same directory. Don’t believe me? Try it!
OK. Now, for Git, in our example, something/something_else, “something” is a directory created in the refs/heads/ directory and “something_else” is a file inside it that hold the branch’s HEAD. So, now we can’t create a directory called “something_else” in the same directory. So, “git checkout -b something/something_else/something_interesting” will give an error.
So, what will we do? One workaround is to give the branch a different name. My favorite workaround is, put an _ (underscore) after”something_else” like, something/something_else_/something_interesting and this will definitely fix the issue. Cool, isn’t it? Try these out and let me know your thoughts!
Originally published at https://anand-jagadeesh.blogspot.com on May 21, 2020.