I have a git repository with multiple branches.
How can I know which branches are already merged into the master branch?
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.
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.
git branch -d
will refuse to delete a branch that has not been merged into the current branch. Not deleting the current branch.
In order to verify which branches are merged into master you should use these commands:
git branch
git branch
Flags Are:
-a flag - (all) showing remote and local branches
-r flag - (remote) showing remote branches only
for example: git branch -r --merged master
will show you all remote repositories merged into master.
git branch -r merged main
will show you branches that you "deleted" on GitHub because GitHub keeps a record of recently deleted PR branches
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
git
client. On Ubuntu, apt-get install gitk
.
brew install git-gui
, to get gitk
on the commandline.
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
}
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
Find last commit hash on master branch Find last commit hash on a "branch" Run command git merge-base
More info on git merge-base https://git-scm.com/docs/git-merge-base.
master
was merged into branch
, and then 4 more commits were added into branch
.
git log -1 $(git merge-base base-branch feature-branch)
and if you see feature-branch
in the output, then you know they are merged?
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
origin/master
but NOT deleted remotely?
git remote prune origin
to update your local machine on what is and is not deleted
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
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)
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"
}
git log --all --color --graph --decorate --topo-order --date=relative --abbrev-commit --pretty=format:"%C(green)%h %C(red bold)[%<(14)%ad] %Creset%s%Cred%d%C(blue) [%an]"
git log
you can add --merges
to only show merge commits. stackoverflow.com/a/25986615/134761
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.
To check whether a source branch has been merged into the master branch, the following bash command can be used:
git merge-base --is-ancestor <source branch name> master && echo "merged" || echo "not merged"
Success story sharing
git branch --merged
and then deleted the local and remote branches.git branch -a --merged/no-merged
does also work, without creating a local tracking branch in the process.git branch -r --merged/--no-merged
to only find remote branches.--merged/--no-merged
takes an optional commit argument after it. At least in my version of git (1.9.1), adding the-a
or-r
flag after it give me a fatal error. Add the-a
or-r
before--(no-)merged
.