Search code examples
gitzshgit-branchparentheses

Complex Git branch name broke all Git commands


I was trying to create a branch from master with the following command,

git branch SSLOC-201_Implement___str__()_of_ProductSearchQuery

when Git suddenly stopped responding. I suspect the unescaped () are to blame, somehow. Now, whenever I try to run any Git command, I get the same error:

git:176: command not found: _of_ProductSearchQuery

with the number after git increasing every time I type a command.

Can anyone explain what happened? And how do I get back to normal? I'd like to delete that branch, but how can I do that?


Solution

  • Problem

    Can anyone explain what happened? [...] I'd love to be able to delete that branch, but Git won't work for me.

    By running

    git branch SSLOC-201_Implement___str__()_of_ProductSearchQuery
    

    in zsh, you did not create any branch. Instead, you accidentally defined three shell functions, called git, branch, and SSLOC-201_Implement___str__, which ignore their parameters (if any) and whose body is _of_ProductSearchQuery. You can check for yourself that this is indeed what happened, by invoking the builtin zsh command called functions, which lists all existing shell functions:

    $ functions                                                     
    SSLOC-201_Implement___str__ () {
        _of_ProductSearchQuery
    }
    branch () {
        _of_ProductSearchQuery
    }
    git () {
        _of_ProductSearchQuery
    }
    

    Unfortunately, although the other two shell functions are not problematic, the shell function called "git" now shadows the bona fide git command!

    $ which git
    git () {
        _of_ProductSearchQuery
    }
    # but the real "git" is a binary file that lives in /usr/local/bin/git (or some similar path)
    

    Therefore, you will subsequently get the error

    command not found: _of_ProductSearchQuery
    

    whenever you attempt to run a Git command, e.g. git log, git status, etc. (assuming, of course, that no command called _of_ProductSearchQuery exists).

    Side note

    [...] I get the same error:

    git:176: command not found: _of_ProductSearchQuery
    

    (with the number after git increasing every time I type a command)

    That number simply corresponds to the value of HISTCMD, an environment variable that holds

    [t]he current history event number in an interactive shell, in other words the event number for the command that caused $HISTCMD to be read.

    See the zsh manual for more details.

    Solution

    And how do I get back to normal?

    Simply delete the problematic shell function (and the other two you created by accident, while you're at it):

    unset -f git
    unset -f branch SSLOC-201_Implement___str__
    

    Then everything should be fine.

    What if unset is shadowed also?!

    Good question! I refer you to Wumpus W. Wumbley's excellent comment below.


    Branch-naming tips

    Avoid any special shell characters

    Yes, as pointed out in the comments, parentheses are valid characters in Git branch names; you just need to quote the name appropriately, e.g.

    $ git branch 'foo()bar'
    $ git branch
      foo()bar
    * master
    $ git checkout 'foo()bar'
    Switched to branch 'foo()bar'
    

    However, the need for quoting such names every single time when used as command-line arguments should convince you to eschew parentheses in reference names. More generally, you should (as much as possible) avoid characters that have a special meaning in shells, to prevent surprises like this one.

    Use simple branch names

    You should keep your branch names short and sweet anyway. Long descriptions like

    SSLOC-201_Implement___str__()_of_ProductSearchQuery

    belong in commit messages, not in branch names.