1260
votes

I have a git repository with multiple branches.

How can I know which branches are already merged into the master branch?

10

10 Answers

1963
votes

git branch --merged master lists branches merged into master

git branch --merged lists branches merged into HEAD (i.e. tip of current branch)

git branch --no-merged lists branches that have not been merged

By default this applies to only the local branches. The -a flag will show both local and remote branches, and the -r flag shows only the remote branches.

126
votes

You can use the git merge-base command to find the latest common commit between the two branches. If that commit is the same as your branch head, then the branch has been completely merged.

Note that git branch -d does this sort of thing already because it will refuse to delete a branch that hasn't already been completely merged.

33
votes

There is a graphical interface solution as well. Just type

gitk --all

A new application window will prompt with a graphical representation of your whole repo, where it is very easy to realize if a branch was already merged or not

29
votes

I am using the following bash function like: git-is-merged develop feature/new-feature

git-is-merged () {
  merge_destination_branch=$1
  merge_source_branch=$2

  merge_base=$(git merge-base $merge_destination_branch $merge_source_branch)
  merge_source_current_commit=$(git rev-parse $merge_source_branch)
  if [[ $merge_base = $merge_source_current_commit ]]
  then
    echo $merge_source_branch is merged into $merge_destination_branch
    return 0
  else
    echo $merge_source_branch is not merged into $merge_destination_branch
    return 1
  fi
}
27
votes

In order to verify which branches are merged into master you should use these commands:

  • git branch <flag[-r/-a/none]> --merged master list of all branches merged into master.
  • git branch <flag[-r/-a/none]> --merged master | wc -l count number of all branches merged into master.

Flags Are:

  • -a flag - (all) showing remote and local branches
  • -r flag - (remote) showing remote branches only
  • <emptyFlag> - showing local branches only

for example: git branch -r --merged master will show you all remote repositories merged into master.

26
votes

Use git merge-base <commit> <commit>.

This command finds best common ancestor(s) between two commits. And if the common ancestor is identical to the last commit of a "branch" ,then we can safely assume that that a "branch" has been already merged into the master.

Here are the steps

  1. Find last commit hash on master branch
  2. Find last commit hash on a "branch"
  3. Run command git merge-base <commit-hash-step1> <commit-hash-step2>.
  4. If output of step 3 is same as output of step 2, then a "branch" has been already merged into master.

More info on git merge-base https://git-scm.com/docs/git-merge-base.

17
votes

On the topic of cleaning up remote branches

git branch -r | xargs -t -n 1 git branch -r --contains

This lists each remote branch followed by which remote branches their latest SHAs are within.

This is useful to discern which remote branches have been merged but not deleted, and which haven't been merged and thus are decaying.

If you're using 'tig' (its like gitk but terminal based) then you can

tig origin/feature/someones-decaying-feature

to see a branch's commit history without having to git checkout

8
votes

I use git for-each-ref to get a list of branches that are either merged or not merged into a given remote branch (e.g. origin/integration)

Iterate over all refs that match <pattern> and show them according to the given <format>, after sorting them according to the given set of <key>.

Note: replace origin/integration with integration if you tend to use git pull as opposed to git fetch.

List of local branches merged into the remote origin/integration branch

git for-each-ref --merged=origin/integration --format="%(refname:short)" refs/heads/
#                ^                           ^                           ^
#                A                           B                           C
branch1
branch2
branch3
branch4

A: Take only the branches merged into the remote origin/integration branch
B: Print the branch name
C: Only look at heads refs (i.e. branches)

List of local branches NOT merged into the remote origin/integration branch

git for-each-ref --no-merged=origin/integration --format="%(committerdate:short) %(refname:short)" --sort=committerdate refs/heads
#                ^                              ^                                                  ^                    ^
#                A                              B                                                  C                    D
2020-01-14 branch10
2020-01-16 branch11
2020-01-17 branch12
2020-01-30 branch13

A: Take only the branches NOT merged into the remote origin/integration branch
B: Print the branch name along with the last commit date
C: Sort output by commit date
D: Only look at heads refs (i.e. branches)

5
votes

Here are my techniques when I need to figure out if a branch has been merged, even if it may have been rebased to be up to date with our main branch, which is a common scenario for feature branches.

Neither of these approaches are fool proof, but I've found them useful many times.

1 Show log for all branches

Using a visual tool like gitk or TortoiseGit, or simply git log with --all, go through the history to see all the merges to the main branch. You should be able to spot if this particular feature branch has been merged or not.

2 Always remove remote branch when merging in a feature branch

If you have a good habit of always removing both the local and the remote branch when you merge in a feature branch, then you can simply update and prune remotes on your other computer and the feature branches will disappear.

To help remember doing this, I'm already using git flow extensions (AVH edition) to create and merge my feature branches locally, so I added the following git flow hook to ask me if I also want to auto-remove the remote branch.

Example create/finish feature branch

554 Andreas:MyRepo(develop)$ git flow start tmp
Switched to a new branch 'feature/tmp'

Summary of actions:
- A new branch 'feature/tmp' was created, based on 'develop'
- You are now on branch 'feature/tmp'

Now, start committing on your feature. When done, use:

     git flow feature finish tmp

555 Andreas:MyRepo(feature/tmp)$ git flow finish
Switched to branch 'develop'
Your branch is up-to-date with 'if/develop'.
Already up-to-date.

[post-flow-feature-finish] Delete remote branch? (Y/n)
Deleting remote branch: origin/feature/tmp.

Deleted branch feature/tmp (was 02a3356).

Summary of actions:
- The feature branch 'feature/tmp' was merged into 'develop'
- Feature branch 'feature/tmp' has been locally deleted
- You are now on branch 'develop'

556 Andreas:ScDesktop (develop)$

.git/hooks/post-flow-feature-finish

NAME=$1
ORIGIN=$2
BRANCH=$3

# Delete remote branch
# Allows us to read user input below, assigns stdin to keyboard
exec < /dev/tty

while true; do
  read -p "[post-flow-feature-finish] Delete remote branch? (Y/n) " yn
  if [ "$yn" = "" ]; then
    yn='Y'    
  fi
  case $yn in
      [Yy] ) 
        echo -e "\e[31mDeleting remote branch: $2/$3.\e[0m" || exit "$?"
        git push $2 :$3; 
        break;;
      [Nn] ) 
        echo -e "\e[32mKeeping remote branch.\e[0m" || exit "$?"
        break;;
      * ) echo "Please answer y or n for yes or no.";;
  esac
done

# Stop reading user input (close STDIN)
exec <&-
exit 0

3 Search by commit message

If you do not always remove the remote branch, you can still search for similar commits to determine if the branch has been merged or not. The pitfall here is if the remote branch has been rebased to the unrecognizable, such as squashing commits or changing commit messages.

  • Fetch and prune all remotes
  • Find message of last commit on feature branch
  • See if a commit with same message can be found on master branch

Example commands on master branch:

gru                   
gls origin/feature/foo
glf "my message"

In my bash .profile config

alias gru='git remote update -p'
alias glf=findCommitByMessage

findCommitByMessage() {
    git log -i --grep="$1"
}
4
votes

Here is a little one-liner that will let you know if your current branch incorporates or is out of data from a remote origin/master branch:

$ git fetch && git branch -r --merged | grep -q origin/master && echo Incorporates origin/master || echo Out of date from origin/master

I came across this question when working on a feature branch and frequently wanting to make sure that I have the most recent work incorporated into my own separate working branch.

To generalize this test I have added the following alias to my ~/.gitconfig:

[alias]
   current = !git branch -r --merged | grep -q $1 && echo Incorporates $1 || echo Out of date from $1 && :

Then I can call:

$ git current origin/master

to check if I am current.