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.
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.
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
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.
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.
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).