Junk Drawer Logo Junk Drawer

For all those little papers scattered across your desk

I stand for the Constitution, for due process, and for community that takes care of each other.

Git Branch Cheat

D. Ben Knoble on 01 Jan 2017 in Blog

Update 2025 January 02: This post is full of my bad, immature scripting ideas; see the BashGuide wiki or Shellcheck for just a few. For repeated operations on many branches, try git for-each-ref. For pushes specifically, you might be able to use the refspec magic git push <remote> :. Otherwise, I’d ignore the rest of this article.

Sometimes, you need to do a particular operation on every single branch in a repo, like pushing or merging. I thought it would be difficult. It’s not.

The Code (Script)

Preface: I do use Bash (no arguing about which shell is best), so this may not apply to everyone. I’m looking at you, Windows people.

for branch in $(ls .git/refs/heads); do
    git checkout $branch
    # git operation on branch
done

Update 2025 January 02: The basename trick below breaks as soon as you use branches with a “directory structure,” like bk/my-work. See the top of the post for better recommendations.

Update It has come to my attention that rather than parsing ls output, we can use globs.

for branch in .git/refs/heads/*; do
    branch="$(basename "$branch")"
    git checkout "$branch"
    # blah blah blah
done

Breaking It Down

The first part is a standard Bash for-loop. Lots of people caution against for loops on files this way, but we’re actually using filenames as branch names, and this is far more readable than using find.

Update 2025 January 02: Don’t parse ls. Just don’t.

The tricky part is $(ls .git/refs/heads). The $() bit means evaluate the parentheses as a shell command. The ls .git/refs/heads bit lists the files in .git/refs/heads, whose names are the names of branches.

Thus, we have a loop over the branch names. git checkout $branch is familiar to git cli users; simply checkout the branch. Then perform any operations on it you’d like. done signals the end of the loop.

Variations

Update 2025 January 02: The semantics with and without quotes are different. Know what you want.

You can optionally quote the branch listing into "$(ls .git/refs/heads)".

You can also follow done with another command, like checking out master again. You would then have done; git checkout master.

Uses

My most frequent uses are pushing all branches to remotes, and merging all branches with master. I only do this when I know it’s a fast-forward merge, but this makes it relatively easy to quickly update all branches with the lastest master developments (probably themselves merged in from one of the branches).


Tags:

Categories: Blog

Load Comments
Previous Next
Back to posts