如何知道一个分支是否已经合并到主分支?

1454

我有一个包含多个分支的git代码库。

如何知道哪些分支已经合并到主分支(master branch)中?

12个回答

2246

git branch --merged master 会列出已经合并到 master 分支的分支列表。

git branch --merged 会列出已经合并到当前分支末端(也就是HEAD)的分支列表。

git branch --no-merged 会列出还未被合并的分支列表。

默认情况下,这只适用于本地分支。-a 标志会显示本地和远程分支,而 -r 标志则仅显示远程分支。


2
只是一点小提示,当我尝试查看远程分支是否已经合并时,我首先设置了一个本地跟踪分支,使用 git branch --merged 确认状态,然后删除了本地和远程分支。 - Kenneth Kalmer
104
显然,git branch -a --merged/no-merged 也可以使用,而无需在此过程中创建本地跟踪分支。 - fresskoma
90
或者只需使用 git branch -r --merged/--no-merged 命令来查找远程分支。 - Asfand Qazi
10
有没有办法在 rebase 后删除实际已合并的未合并分支? - Ashfame
11
请注意,--merged/--no-merged 在其后可以接受一个可选的提交参数。至少在我的git版本(1.9.1)中,在其后添加-a-r标志会导致致命错误。应该在--(no-)merged之前添加-a-r标志。 - jgawrych
显示剩余12条评论

149

您可以使用git merge-base命令找到两个分支之间最新的公共提交。如果该提交与您的分支头相同,则分支已完全合并。

请注意,git branch -d已经实现了这种功能,因为它会拒绝删除尚未完全合并的分支。


7
@hari的答案更详细地介绍了如何使用这个。 - Muhd
3
还没有完全合并到哪个分支? - Alexander Mills
2
@AlexanderMills:合并到你当前的分支。 - Greg Hewgill
3
git branch -d 命令拒绝删除尚未合并到当前分支的分支,不会删除当前分支。 - Greg Hewgill
git branch -d。我正在运行命令从完全提交的分支中,但它仍然说它没有完全提交。 - Jason G
显示剩余3条评论

49
为了确认哪些分支合并到了主分支,您应该使用以下命令:
  • git branch <flag[-r/-a/none]> --merged master 列出所有合并到主分支的分支。
  • git branch <flag[-r/-a/none]> --merged master | wc -l 统计合并到主分支的所有分支数量。

标志位包括:

  • -a 标志 - 显示本地和远程分支 (all)
  • -r 标志 - 显示远程分支 (remote)
  • <emptyFlag> - 只显示本地分支 local

例如: git branch -r --merged master 将会展示所有合并到主分支的远程仓库。


感谢您提供这个出色的答案。非常有帮助且易于使用。应该将其设置为答案,因为它使用了git(而不是第三方工具)。 - raddevus
git branch -r merged main 会显示你在 GitHub 上“删除”的分支,因为 GitHub 会记录最近删除的 PR 分支 - Chuan
你如何解释输出?当我执行 git branch --merged master 命令时,它会输出 "master"。但如果我对我的 develop 分支执行相同的命令,它会列出一些功能分支以及 develop 和 master 分支。 - Ken Hadden

39

还有一个图形界面的解决方案。只需要输入

gitk --all

一个新的应用程序窗口将出现,其中显示了你的整个存储库的图形表示,非常容易判断分支是否已经合并。


24
需要说明的是,这需要安装一个不属于 git 客户端的应用程序。在 Ubuntu 上,可以使用命令 apt-get install gitk 进行安装。 - metame
3
在 macOS 上,如果您已经安装了 Homebrew,则可以使用“brew install git-gui”命令来获取命令行上的“gitk”。 - program247365

34

使用 git merge-base <commit> <commit> 命令,查找两个提交之间的最佳共同祖先。如果共同祖先与 "分支" 的最后一个提交相同,则可以安全地假定该 "分支" 已经合并到主分支中。

以下是步骤:

  1. 在主分支上找到最新的提交哈希值
  2. 在 "分支" 上找到最新的提交哈希值
  3. 运行命令 git merge-base <commit-hash-step1> <commit-hash-step2>
  4. 如果第3个步骤的输出与第2个步骤的输出相同,则 "分支" 已经被合并到主分支中了。

有关 git merge-base 的更多信息,请参见https://git-scm.com/docs/git-merge-base


2
我认为这只能告诉你是否合并了差异。例如,这不能告诉您如果master已经合并到branch,然后又添加了4次提交到branch - mkobit
为什么不使用git log -1 $(git merge-base base-branch feature-branch),如果在输出中看到feature-branch,那么你就知道它们已经合并了。 - Carl G

33

我正在使用下面的bash函数: 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
}

5
这实际上不起作用了。如果源分支已经合并到目标分支,然后目标分支又有了几个提交,它就不再起作用了,但我不知道为什么。 - Alexander Mills
1
请查看此处的问题:https://dev59.com/DKzla4cB1Zd3GeqPEeul - Alexander Mills
1
@AlexanderMills 即使在合并源分支后目标分支有更多的提交,对我来说它也能正常工作。 - Grodriguez

20
关于清理远程分支的话题
git branch -r | xargs -t -n 1 git branch -r --contains

这会列出每个远程分支,以及它们最新的SHA所在的远程分支。
这对于区分已合并但未删除的远程分支和未合并且正在消失的分支非常有用。
如果您使用的是“tig”(类似于gitk但基于终端),则可以。
tig origin/feature/someones-decaying-feature

无需 git checkout 即可查看分支的提交历史记录


3
干得好!一旦你理解了它实际显示的内容,它就非常有用!GitHub应用程序需要将其纳入分支的可视化显示中,而不是以字母顺序列出没有层级结构的列表! - CMash
这个命令显示已经合并到 origin/master 但是没有在远程删除的分支? - Chris F
我认为你可能需要运行 git remote prune origin 命令来更新本地机器上已删除和未删除的内容。 - xxjjnn

14

我使用git for-each-ref获取已合并或未合并到给定远程分支(例如origin/integration)的分支列表。

遍历所有与<pattern>匹配的引用,按照给定的<key>集进行排序,并根据给定的<format>显示它们。

注意:如果你倾向于使用git pull而不是git fetch,请将origin/integration替换为integration

合并到远程origin/integration分支的本地分支列表

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

A: 仅获取合并到远程 origin/integration 分支中的分支
B: 打印分支名称
C: 仅查看 heads 引用(即分支)

未合并到远程 origin/integration 分支中的本地分支列表

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: 只获取未合并到远程 origin/integration 分支的分支
B: 输出分支名和最后一次提交日期
C: 按提交日期对输出进行排序
D: 仅查看 heads 引用(即分支)


这个命令对我不起作用 -- 未合并到远程 origin/integration 分支的本地分支列表 - Rahul Vyas

9
为了检查源分支是否已经合并到主分支,可以使用以下Bash命令:
git merge-base --is-ancestor <source branch name> master && echo "merged" || echo "not merged"

7
这是我在需要确定一个分支是否已合并时使用的技巧,即使它已被重新设置为与我们的主分支保持最新状态,这是特性分支的常见情况。
这两种方法都不是百分之百可靠的,但我发现它们很有用。
1 显示所有分支的日志
使用像gitk或TortoiseGit这样的可视化工具,或者只需使用--all选项的git log,浏览历史记录以查看所有合并到主分支的内容。您应该能够判断出是否已合并此特定特性分支。
2 始终在合并特性分支时删除远程分支
如果您有一个良好的习惯,在合并特性分支时始终删除本地和远程分支,那么您只需在其他计算机上更新和修剪远程分支,特性分支就会消失。
为了帮助记住这样做,我已经使用 git flow extensions (AVH edition)来在本地创建和合并我的特性分支,因此我添加了以下git flow钩子来询问我是否还要自动删除远程分支。
示例创建/完成特性分支
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按提交信息搜索

如果您不总是删除远程分支,则仍然可以搜索类似的提交以确定该分支是否已合并。这里的陷阱是,如果远程分支已被重新设置为不可识别的状态,例如压缩提交或更改提交消息。

  • 拉取和修剪所有远程分支
  • 查找功能分支上的最后一次提交消息
  • 查看主分支上是否可以找到具有相同消息的提交

主分支上的示例命令:

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

在我的bash .profile配置中

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

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

@anjdeas - 步骤1 - 你怎么知道哪些分支已经合并到主分支了。我一直在查看日志和GUI工具,但无法找到任何明确显示这一点的地方??? - The Huff
@TheHuff 试试这个命令: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]" - angularsen
在TortoiseGit中,如果您在主分支上,它应该显示所有合并到主分支的内容。 - angularsen
谢谢 - 但是我怎么知道什么是合并?我假设它们都是提交 - 这对吗? - The Huff
@TheHuff:你应该可以在视图日志中看到两个提交流/路径合并为一个“下游”提交(在日志视图中更高)。那个提交是一个合并提交。此外,在 git log 中,您可以添加 --merges 以仅显示合并提交。https://dev59.com/618e5IYBdhLWcg3wNIFp#25986615 - angularsen
我喜欢使用 git log -i --grep="<summary>" 方法,因为它似乎对于已经被 rebase 到主分支的分支也很有效(只要你要查找的提交没有被压缩在一起)。使用这种方法,我可以轻松地检查该查询在我的主分支上输出的提交作者和日期与我的次要分支日志相匹配。 - TafT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接