Git Weekly 3 - fast and furious

| 2 min read

📋 Summary

This week, I’m going to share with you a git command that illustrates my dark side as a developer. So hang on tight!

Can I have a branch and a tag with the same name in git? #

In this thread, Pierre-Yves explains that git doesn’t handle having the same name for a branch and a tag very well.

If you attended the talk on git internals[1] , you know that branches and tags are just named pointers to a commit. And they are not referenced in the same place. It is therefore possible to have a tag with the same name as a branch.

However, you should be aware that some git commands give priority to branch names and others to tag names. This can lead to problems or errors. If you encounter this kind of problem, you should use the absolute reference, for example :

# let's have a branch and a tag with the same name in git
$ git branch
* my-duplicate-name

$ git tag -l

# when we switch to the branch, git warns about the issue but do the switch to the right branch
$ git switch my-duplicate-name
warning: refname 'my-duplicate-name' is ambiguous.
Switched to branch 'my-duplicate-name'

# but git is obviously unable to make the diff between them
$ git diff --shortstat
warning: refname 'my-duplicate-name' is ambiguous.
warning: refname 'my-duplicate-name' is ambiguous.

# in order to fix it, we must use the absolute git reference of the branch and the tag
$ git diff --shortstat refs/heads/my-duplicate-name..refs/tags/my-duplicate-name
 1 file changed, 24 deletions(-)

Nevertheless, it is preferable to have a different naming convention between branches and tags to avoid this kind of situation. Especially as a branch and a tag do not have the same purpose. A tag provides an immutable snapshot of content at a given moment. A branch, on the other hand, tracks the latest changes made on that branch of the git history tree.

How to overwrite the last remote git commit with all local modifications? #

Sometimes, as a developer, we find ourselves in a mode I call “test, fail and retry”. You commit a change, push the change and test it. It doesn’t work the first time. So we start again. You end up with a series of “wip” commits (for work in progress). Personally, I find this very ugly. So I prefer to overwrite the last commit with my latest changes. So here’s my command, which adds all local changes to the last commit and overwrites the commit on the remote repository:

git commit -a --amend --no-edit && git push prod --force-with-lease

I use this command so much that I’ve created an alias for it[2]:

git config --global alias.faf '!git commit -a --amend --no-edit && git push prod --force-with-lease'

This allows me to make a simple git faf. 😈

So yes, it’s possible to make lots of “wip” commits, and then at merge time do a squash. But I’m not going to lie to you. That’s not what I do every day.

Want to learn more about git? Check out the Git Weekly series!

  1. That I gave in French (sorry) at Devoxx France. ↩︎

  2. Did you note this push prod --force? It looks like a nod to the long-ago days of FTP development on the production or prequel of a series of horror stories. ↩︎