ChatGPT解决这个技术问题 Extra ChatGPT

How can I know if a branch has been already merged into master?

git

I have a git repository with multiple branches.

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


J
Jake Berger

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.


Just a side note, when I tried to see if a remote branch had been merged I first setup a local tracking branch, identified the status with git branch --merged and then deleted the local and remote branches.
Apparently, git branch -a --merged/no-merged does also work, without creating a local tracking branch in the process.
Or just git branch -r --merged/--no-merged to only find remote branches.
Any way to delete unmerged branches which were actually merged after rebasing?
Note that --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.
P
Palec

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.


@hari's answer goes into more detail on how to use this.
how can we do this automatically/programmatically?
"hasn't already been completely merged" ... completely merged into what branch?
@AlexanderMills: Into your current branch.
@AlexanderMills: git branch -d will refuse to delete a branch that has not been merged into the current branch. Not deleting the current branch.
a
avivamg

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

git branch --merged master list of all branches merged into master.

git branch --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

- showing local branches only

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


Thanks for this great answer. very helpful and easy to use. This should be set to the answer because it uses git (and not a 3rd party item).
git branch -r merged main will show you branches that you "deleted" on GitHub because GitHub keeps a record of recently deleted PR branches
i
iberbeu

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


Which to be clear, requires the installation of an application that is not part of the git client. On Ubuntu, apt-get install gitk.
On macOS, if you have Homebrew installed, would be brew install git-gui, to get gitk on the commandline.
C
Carl G

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
}

this actually doesn't work. If the source branch has been merged into the destination branch already, and then destination branch gets a few more commits, it doesn't work anymore but I don't know why
@AlexanderMills It works fine for me even if the destination branch gets a few more commits after merging the source branch
H
Hari

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


I think this will only tell you if the tips are merged. For example, this won't tell you if master was merged into branch, and then 4 more commits were added into branch.
Why not 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?
x
xxjjnn

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


Well done that man! Very useful once you get your head around what it's actually displaying! The GitHub app needs to incorporate this into a visual display of your branches, rather than an alphabetised list with no hierarchy!
So this command shows branches that have been merged to origin/master but NOT deleted remotely?
I think so... you might need to run git remote prune origin to update your local machine on what is and is not deleted
c
customcommander

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 and show them according to the given , after sorting them according to the given set of .

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)


This command is not working for me -- List of local branches NOT merged into the remote origin/integration branch
a
angularsen

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"
}

@anjdeas - step 1 - how do you know which branches have been merged into main. I've been looking at the logs and gui tools - and cannot find anywhere where it explicitly shows this???
@TheHuff Try this: 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]"
@TheHuff In TortoiseGit, if you are on the main branch, it should show all merges into main.
Thanks - but how do I know what is a merge? I'm assuming they are all commits - is this right?
@TheHuff: You should visually see two streams/paths of commits merge together to a single commit "downstream" (higher up in log view). That commit is a merge commit. Also, in git log you can add --merges to only show merge commits. stackoverflow.com/a/25986615/134761
r
radke

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.


H
Harish Ambady

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"