Search code examples
gitgit-branch

git branch -r --no-merged lists already merged branches


We keep our kickstart code in a git repository so it is consistent across all kickstart servers. We have a small script to display all current branches, ask which one you want to use and then pulls that down and makes sure the code is readable by all. A portion of the code:

git checkout main >/dev/null 2>&1
git fetch --all >/dev/null 2>&1
git pull >/dev/null 2>&1
git branch -r --no-merged
echo "  main"

Instead of listing just the unmerged branches, it lists just about every branch we've ever had. What am I doing wrong?


Solution

  • Instead of listing just the unmerged branches, it lists just about every branch we've ever had.

    This is likely happening because Git doesn't actually merge branches, but instead merges commits. Take any branch that you see which you expect should not be there, and try this command:

    git log main..<some-branch-name>
    

    This will show you all the commits that are "on" that branch that aren't "on" main. If the output of that command is blank, then by definition that branch is fully merged.

    Some reasons that most of the branches could be "not merged" are:

    1. When merging the branches, a strategy is used which rewrites the commits getting merged in. Some common merge strategies in popular tools are called things like: squash merge, rebase merge or semi-linear merge, and rebase fast-forward. If any of those strategies were used, and if the original feature branch was not rewritten and also not deleted, then they will all be sitting out there as unmerged.
    2. At some point in the past, your main branch was rewritten, but the feature branches were not.
    3. After the feature branches were merged, more commits were added to those feature branches, perhaps due to branch name re-use.
    4. If the workflow is such that users happen to push a lot of branches for work in progress before settling on a final branch at the end, you might just have a bunch of old work in progress branches that the devs never bothered to clean up.

    You can easily prove if #1 is the culprit: when you run the command above, search for the commits that are listed, to see if they also exist in main, but with different commit IDs. If the commit messages, authors and dates are the same, but they have different commit dates and commit IDs, then this points to a rebase merge or rebase fast-forward strategy that also does not rewrite the feature branch before doing the merge.

    Side Note: if #1 is the reason, consider deleting your feature branches after merging them into main. (This is a setting on most tools that offer Pull/Merge requests.)