git 删除不再远程的跟踪分支
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7726949/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Remove tracking branches no longer on remote
提问by Mailo Světel
Is there a simple way to delete all tracking branches whose remote equivalent no longer exists?
是否有一种简单的方法可以删除所有远程等效项不再存在的跟踪分支?
Example:
例子:
Branches (local and remote)
分支机构(本地和远程)
- master
- origin/master
- origin/bug-fix-a
- origin/bug-fix-b
- origin/bug-fix-c
- 掌握
- 起源/主人
- 起源/错误修复-a
- 起源/错误修复-b
- 起源/错误修复-c
Locally, I only have a master branch. Now I need to work on bug-fix-a, so I check it out, work on it, and push changes to the remote. Next I do the same with bug-fix-b.
在本地,我只有一个 master 分支。现在我需要处理bug-fix-a,所以我检查它,处理它,并将更改推送到远程。接下来我对bug-fix-b做同样的事情。
Branches (local and remote)
分支机构(本地和远程)
- master
- bug-fix-a
- bug-fix-b
- origin/master
- origin/bug-fix-a
- origin/bug-fix-b
- origin/bug-fix-c
- 掌握
- 错误修复-a
- 错误修复-b
- 起源/主人
- 起源/错误修复-a
- 起源/错误修复-b
- 起源/错误修复-c
Now I have local branches master, bug-fix-a, bug-fix-b. The Master branch maintainer will merge my changes into masterand delete all branches he has already merged.
现在我有本地分支master,bug-fix-a,bug-fix-b。Master 分支维护者会将我的更改合并到master并删除他已经合并的所有分支。
So the current state is now:
所以现在的状态是:
Branches (local and remote)
分支机构(本地和远程)
- master
- bug-fix-a
- bug-fix-b
- origin/master
- origin/bug-fix-c
- 掌握
- 错误修复-a
- 错误修复-b
- 起源/主人
- 起源/错误修复-c
Now I would like to call some command to delete branches (in this case bug-fix-a, bug-fix-b), which are no longer represented in the remote repository.
现在我想调用一些命令来删除分支(在这种情况下是bug-fix-a,bug-fix-b),这些分支不再出现在远程存储库中。
It would be something like the existing command git remote prune origin
, but more like git local prune origin
.
它类似于现有的命令git remote prune origin
,但更像是git local prune origin
.
回答by aubreypwd
git remote prune origin
prunes tracking branches not on the remote.
git remote prune origin
修剪不在遥控器上的跟踪分支。
git branch --merged
lists branches that have been merged into the current branch.
git branch --merged
列出已经合并到当前分支的分支。
xargs git branch -d
deletes branches listed on standard input.
xargs git branch -d
删除标准输入上列出的分支。
Be careful deleting branches listed by git branch --merged
. The list could include master
or other branches you'd prefer not to delete.
小心删除由 列出的分支git branch --merged
。该列表可能包括master
您不想删除的或其他分支。
To give yourself the opportunity to edit the list before deleting branches, you could do the following in one line:
为了让自己有机会在删除分支之前编辑列表,您可以在一行中执行以下操作:
git branch --merged >/tmp/merged-branches && \
vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches
回答by jason.rickman
After the command
命令后
git fetch -p
removes the remote references, when you run
运行时删除远程引用
git branch -vv
it will show 'gone' as the remote status. For example,
它将显示“gone”作为远程状态。例如,
$ git branch -vv
master b900de9 [origin/master: behind 4] Fixed bug
release/v3.8 fdd2f4e [origin/release/v3.8: behind 2] Fixed bug
release/v3.9 0d680d0 [origin/release/v3.9: behind 2] Updated comments
bug/1234 57379e4 [origin/bug/1234: gone] Fixed bug
So you can write a simple script to remove local branches that have gone remotes:
所以你可以编写一个简单的脚本来删除已经远程的本地分支:
git fetch -p && for branch in $(git branch -vv | grep ': gone]' | awk '{print }'); do git branch -D $branch; done
Note that the above uses the "porcelain" command git branch
to get the upstream status.
请注意,上面使用“瓷器”命令git branch
来获取上游状态。
Another way to obtain this status is to use the "plumbing" command git for-each-ref
with the interpolation variable %(upstream:track)
, which will be [gone]
just like above.
获得这种状态的另一种方法是使用“管道”命令git for-each-ref
与所述内插变量%(upstream:track)
,这将是[gone]
一样的上方。
This approach is somewhat safer, because there is no risk of accidentally matching on part of the commit message.
这种方法更安全一些,因为不存在意外匹配部分提交消息的风险。
git fetch -p && for branch in $(git for-each-ref --format '%(refname) %(upstream:track)' refs/heads | awk ' == "[gone]" {sub("refs/heads/", "", ); print }'); do git branch -D $branch; done
回答by dlsso
Most of these answers do not actually answer the original question. I did a bunch of digging and thiswas the cleanest solution I found. Here is a slightly more thorough version of that answer:
大多数这些答案实际上并没有回答原始问题。我做了很多挖掘,这是我找到的最干净的解决方案。这是该答案的稍微更彻底的版本:
- Check out your default branch. Usually
git checkout master
- Run
git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d
- 查看您的默认分支。通常
git checkout master
- 跑
git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d
Explanation:
解释:
Works by pruning your tracking branches then deleting the local ones that show they are "gone" in git branch -vv
.
通过修剪您的跟踪分支然后删除显示它们在git branch -vv
.
Notes:
笔记:
If your language is set to something other than English you will need to change gone
to the appropriate word. Branches that are local only will not be touched. Branches that have been deleted on remote but were not merged will show a notification but not be deleted on local. If you want to delete those as well change -d
to -D
.
如果您的语言设置为英语以外的其他语言,则需要更改gone
为适当的单词。仅本地的分支将不会被触及。已在远程删除但未合并的分支将显示通知但不会在本地删除。如果你想删除那些也更改-d
为-D
.
回答by Andrew Spencer
I wouldn't normally answer a question that already has 16 answers, but all the other answers are wrong, and the right answer is so simple. The question says, "Is there a simple way to delete all tracking branches whose remote equivalent no longer exists?"
我通常不会回答一个已经有 16 个答案的问题,但所有其他答案都是错误的,正确的答案就是如此简单。问题是,“有没有一种简单的方法可以删除所有远程等效项不再存在的跟踪分支?”
If "simple" means deleting them all in one go, not fragile, not dangerous, and without reliance on tools that not all readers will have, then the right answer is: no.
如果“简单”意味着一次性将它们全部删除,不脆弱,不危险,并且不依赖并非所有读者都会拥有的工具,那么正确的答案是:不。
Some answers are simple, but they don't do what was asked. Others do what was asked, but are not simple: all rely on parsing Git output through text-manipulation commands or scripting languages, which may not be present on every system. On top of that, most of the suggestions use porcelain commands, whose output is not designed to be parsed by script ("porcelain" refers to the commands intended for human operation; scripts should use the lower-level "plumbing" commands).
有些答案很简单,但他们并没有按照要求去做。其他人按要求执行,但并不简单:所有这些都依赖于通过文本操作命令或脚本语言解析 Git 输出,这可能并非在每个系统上都存在。最重要的是,大多数建议使用瓷器命令,其输出不是设计为由脚本解析的(“瓷器”是指用于人类操作的命令;脚本应使用较低级别的“管道”命令)。
Further reading:
进一步阅读:
- why you shouldn't parse
git branch
output in a script. - tracking branches and the differences between
git remote prune
,git prune
,git fetch --prune
If you want to do this safely, for the use case in the question (garbage-collect tracking branches which have been deleted on the server but still exist as local branches) and with high-level Git commands only, you have to
如果您想安全地执行此操作,对于问题中的用例(已在服务器上删除但仍作为本地分支存在的垃圾收集跟踪分支)并且仅使用高级 Git 命令,您必须
git fetch --prune
(orgit fetch -p
, which is an alias, orgit prune remote origin
which does the same thing without fetching, and is probably not what you want most of the time).- Note any remote branches that are reported as deleted. Or, to find them later on,
git branch -v
(any orphaned tracking branch will be marked "[gone]"). git branch -d [branch_name]
on each orphaned tracking branch
git fetch --prune
(或者git fetch -p
,这是一个别名,或者git prune remote origin
在不获取的情况下执行相同的操作,并且可能在大多数情况下不是您想要的)。- 请注意报告为已删除的任何远程分支。或者,为了稍后找到它们,
git branch -v
(任何孤立的跟踪分支都将被标记为“[gone]”)。 git branch -d [branch_name]
在每个孤立的跟踪分支上
(which is what some of the other answers propose).
(这是其他一些答案所提出的)。
If you want to script a solution, then for-each-ref
is your starting point, as in Mark Longair's answerhere and this answer to another question, but I can't see a way to exploit it without writing a shell script loop, or using xargs or something.
如果你想编写一个解决方案,那么for-each-ref
你的起点就是你的起点,就像Mark Longair在这里的回答和另一个问题的回答一样,但我看不到一种方法来利用它而不编写 shell 脚本循环,或者使用 xargs 或其他东西.
Background explanation
背景说明
To understand what's happening, you need to appreciate that, in the situation of tracking branches, you have not one branch, but three. (And recall that "branch" means simply a pointer to a commit.)
要了解发生了什么,您需要意识到,在跟踪分支的情况下,您没有一个分支,而是三个。(回想一下,“分支”只是一个指向提交的指针。)
Given a tracking branch feature/X
, the remote repository (server) will have this branch and call it feature/X
. Your local repository has a branch remotes/origin/feature/X
which means, "This is what the remote told me its feature/X branch was, last time we talked," and finally, the local repository has a branch feature/X
which points to your latest commit, and is configured to "track" remotes/origin/feature/X
, meaning that you can pull and push to keep them aligned.
给定一个跟踪分支feature/X
,远程存储库(服务器)将拥有这个分支并调用它feature/X
。您的本地存储库有一个分支remotes/origin/feature/X
,这意味着“这是远程告诉我它的功能/X 分支是什么,我们上次交谈时”,最后,本地存储库有一个feature/X
指向您最新提交的分支,并配置为"track" remotes/origin/feature/X
,这意味着您可以拉动和推动以保持它们对齐。
At some point, someone has deleted the feature/X
on the remote. From that moment, you are left with your local feature/X
(which you probably don't want any more, since work on feature X is presumably finished), and your remotes/origin/feature/X
which is certainly useless because its only purpose was to remember the state of the server's branch.
在某些时候,有人删除feature/X
了遥控器上的 。从那一刻起,你只剩下你的本地feature/X
(你可能不想再想要了,因为功能 X 的工作大概已经完成),而你的remotes/origin/feature/X
这肯定没用,因为它的唯一目的是记住服务器分支的状态.
And Git will let you automatically clean up the redundant remotes/origin/feature/X
-- that's what git fetch --prune
does -- but for some reason, it doesn't let you automatically delete your own feature/X
... even though your feature/X
still contains the orphaned tracking information, so it has the information to identify former tracking branches that have been fully merged. (After all, it can give youthe information that lets you do the operation by hand yourself.)
Git 会让你自动清理多余的remotes/origin/feature/X
——就是git fetch --prune
这样——但出于某种原因,它不会让你自动删除你自己的feature/X
......即使你feature/X
仍然包含孤立的跟踪信息,所以它有信息识别已完全合并的前跟踪分支。(毕竟它可以给你信息,让你自己动手操作。)
回答by karlingen
I found the answer here: How can I delete all git branches which have been merged?
我在这里找到了答案: 如何删除所有已合并的 git 分支?
git branch --merged | grep -v "\*" | xargs -n 1 git branch -d
Make sure we keep master
确保我们保持主人
You can ensure that master
, or any other branch for that matter, doesn't get removed by adding another grep
after the first one. In that case you would go:
您可以master
通过grep
在第一个分支之后添加另一个分支来确保或任何其他分支不会被删除。在那种情况下,你会去:
git branch --merged | grep -v "\*" | grep -v "YOUR_BRANCH_TO_KEEP" | xargs -n 1 git branch -d
So if we wanted to keep master
, develop
and staging
for instance, we would go:
因此,如果我们想继续保持master
,develop
并staging
举例来说,我们会去:
git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d
Make this an alias
将此设为别名
Since it's a bit long, you might want to add an alias to your .zshrc
or .bashrc
. Mine is called gbpurge
(for git branches purge
):
由于它有点长,您可能需要为您的.zshrc
或.bashrc
. 我的被称为gbpurge
(对于git branches purge
):
alias gbpurge='git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d'
Then reload your .bashrc
or .zshrc
:
然后重新加载您的.bashrc
or .zshrc
:
. ~/.bashrc
or
或者
. ~/.zshrc
回答by chris31389
Windows Solution
视窗解决方案
For Microsoft Windows Powershell:
对于 Microsoft Windows Powershell:
git checkout master; git remote update origin --prune; git branch -vv | Select-String -Pattern ": gone]" | % { $_.toString().Trim().Split(" ")[0]} | % {git branch -d $_}
git checkout master; git remote update origin --prune; git branch -vv | Select-String -Pattern ": gone]" | % { $_.toString().Trim().Split(" ")[0]} | % {git branch -d $_}
Explaination
说明
git checkout master
switches to the master branch
git checkout master
切换到主分支
git remote update origin --prune
prunes remote branches
git remote update origin --prune
修剪远程分支
git branch -vv
gets a verbose output of all branches (git reference)
git branch -vv
获取所有分支的详细输出(git reference)
Select-String -Pattern ": gone]"
gets only the records where they have been removed from remote.
Select-String -Pattern ": gone]"
仅获取已从远程删除的记录。
% { $_.toString().Trim().Split(" ")[0]}
get the branch name
% { $_.toString().Trim().Split(" ")[0]}
获取分支名称
% {git branch -d $_}
deletes the branch
% {git branch -d $_}
删除分支
回答by Patrick Quirk
The pattern matching for "gone" in most of the other solutions was a little scary for me. To be safer, this uses the --format
flag to pull out each branch's upstream tracking status.
大多数其他解决方案中“gone”的模式匹配对我来说有点可怕。为了更安全,这使用--format
标志来拉出每个分支的上游跟踪状态。
I needed a Windows-friendly version, so this deletes all branches that are listed as "gone" using Powershell:
我需要一个 Windows 友好的版本,所以这会删除所有使用 Powershell 列为“gone”的分支:
git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" |
? { $_ -ne "" } |
% { git branch -D $_ }
The first line lists the name of local branches whose upstream branch is "gone". The next line removes blank lines (which are output for branches that aren't "gone"), then the branch name is passed to the command to delete the branch.
第一行列出了上游分支“消失”的本地分支的名称。下一行删除空行(它们是未“消失”的分支的输出),然后将分支名称传递给命令以删除分支。
回答by cs01
Remove all branches that have been merged into master, but don't try to remove master itself:
删除所有已合并到 master 中的分支,但不要尝试删除 master 本身:
git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)
git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)
or add an alias:
或添加别名:
alias gitcleanlocal="git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)"
alias gitcleanlocal="git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)"
Explanation:
解释:
git checkout master
checkout master branch
git checkout master
结帐主分支
git pull origin master
ensure local branch has all remote changes merged
git pull origin master
确保本地分支合并所有远程更改
git fetch -p
remove references to remote branches that have been deleted
git fetch -p
删除对已删除远程分支的引用
git branch -d $(git branch master --merged | grep master -v)
delete all branches that have been merged into master, but don't try to remove master itself
git branch -d $(git branch master --merged | grep master -v)
删除所有已经合并到master的分支,但不要尝试删除master本身
回答by ckirksey3
git fetch -p
This will pruneany branches that no longer exist on the remote.
这将修剪远程上不再存在的任何分支。
回答by bxm
Yet-another-answer for the pile, drawing heavily from Patrick's answer(which I like because it seems to do away with any ambiguity about where gone]
will match in the git branch
output) but adding a *nix bent.
一堆的另一个答案,大量借鉴了帕特里克的答案(我喜欢它,因为它似乎消除了关于输出中gone]
匹配位置的任何歧义git branch
),但添加了 *nix 弯曲。
In its simplest form:
以其最简单的形式:
git branch --list --format \
"%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" \
| xargs git branch -D
I have this wrapped up in a git-gone
script on my path:
我将它封装git-gone
在我路径上的脚本中:
#!/usr/bin/env bash
action() {
${DELETE} && xargs git branch -D || cat
}
get_gone() {
git branch --list --format \
"%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)"
}
main() {
DELETE=false
while [ $# -gt 0 ] ; do
case "" in
(-[dD] | --delete) DELETE=true ;;
esac
shift
done
get_gone | action
}
main "${@}"
NB - The --format
option seems to be fairly new; I needed to upgrade git from 2.10.something to 2.16.3 to get it.
注意 - 该--format
选项似乎相当新;我需要将 git 从 2.10.something 升级到 2.16.3 才能得到它。
EDIT: tweaked to include suggestion about refname:short
from Benjamin W.
编辑:调整以包含refname:short
来自Benjamin W.
NB2 - I've only tested in bash
, hence the hashbang, but probably portable to sh
.
NB2 -我只在测试bash
,因此hashbang,但可能移植到sh
。