使用Git fetch或pull自动修剪

326

如果有人因为工作已经结束而删除了远程分支,而我并不知道,我就不会执行git fetch --prune,最终会将被删除的分支推送回去。

是否有一种可行的解决方案,可以在获取/拉取时强制Git使用修剪模式,而无需每次都指定它?


2
你很快就可以(在git 1.8.5,2013年第四季度)能够在仓库的本地配置中指定你希望始终git fetch时进行修剪!请参见我下面的答案 - VonC
4个回答

512

自从 Git 1.8.5(2013年第四季度)以来:

"git fetch"(因此 "git pull" 也一样)学会了检查 "fetch.prune" 和 "remote.*.prune" 配置变量,并且表现得好像给出了 "--prune" 命令行选项。

这意味着,如果您将 remote.origin.prune 设置为 true:

git config remote.origin.prune true

任何git fetch或者git pull都会自动清除。
注意:Git 2.12(2017年第一季度)将修复与此配置相关的错误,这将导致git remote rename不正常工作。
请参见“如何重命名git远程?”。

请查看commit 737c5a9的更多信息:

没有 "git fetch --prune" 命令,远程跟踪分支将永久存在于本地,即使对方已经删除了这些分支。有些人想始终运行 "git fetch --prune" 命令。
为了满足希望总是修剪或从特定远程获取时修剪的用户,添加两个新的配置变量 "fetch.prune" 和 "remote.<name>.prune":
  • "fetch.prune" 允许启用所有获取操作的修剪。
  • "remote.<name>.prune" 允许更改每个远程的行为。
后者自然会覆盖前者,并且命令行中的 --[no-]prune 选项将覆盖配置的默认值。
由于 --prune 是一项潜在具有破坏性的操作(Git 尚未为已删除的引用保留 reflog),我们不希望在没有用户同意的情况下进行修剪,因此此配置不会默认开启。

1
我希望在所有的git仓库中默认使用这种行为。有没有办法将其放入我的.gitconfig文件中以实现这一点? - Andrew
70
@Andrew 一个好的开始是 git config --global fetch.prune true - VonC
3
总体翻译:如果一直在拉取时进行修剪,可能会有哪些潜在的缺点?引用提到了 reflog 历史记录会受到影响,但这可能会引入什么实际问题?可能存在的译文: 在每次拉取时进行修剪可能存在以下潜在缺点:由于 reflog 历史记录会受到影响,这可能会导致实际问题。 - Grapho
5
@Grapho 没有真正的不利之处,但是...请查看 https://dev59.com/OlkS5IYBdhLWcg3wb2Xs#39862779 了解更多信息。 - VonC

260

git config --global fetch.prune true

为了让所有的Git仓库在执行git fetchgit pull命令时,总是自动执行--prune操作,请使用上述Git命令进行全局配置。

git config --global fetch.prune true

这个命令将以下内容添加到您的全局Git配置文件中(通常位于~/.gitconfig)。使用git config -e --global查看您的全局配置。

[fetch]
    prune = true

git config remote.origin.prune true

始终--prune,但仅适用于一个存储库:

git config remote.origin.prune true
                 #^^^^^^
                 #replace with your repo name

上述命令将以下最后一行添加到您的本地Git配置文件(通常为.git/config)。使用git config -e查看您的本地配置。

[remote "origin"]
    url = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    fetch = +refs/heads/*:refs/remotes/origin/*
    prune = true

在第二个命令中也可以使用--global,或者在第一个命令中使用--local


git config --global gui.pruneDuringFetch true

如果你使用git gui,你可能会对以下内容感兴趣:

git config --global gui.pruneDuringFetch true

添加以下内容:

[gui]
    pruneDuringFetch = true

参考资料

来自 git 帮助文档 的相关说明:

--global

  写入配置:写入全局的 ~/.gitconfig 文件,而非仓库的 .git/config 文件。如果 $XDG_CONFIG_HOME/git/config 文件存在,则写入该文件。如果 ~/.gitconfig 文件不存在,则会创建该文件。

 

--local

  写入配置:写入仓库的 .git/config 文件。这是默认行为。

 

fetch.prune

  如果设置为 true,在执行 fetch 命令时会自动加上 --prune 选项。也可参见 remote.<name>.prune 设置。

 

gui.pruneDuringFetch

  如果设置为 "true",在使用 git-gui 执行 fetch 命令时会同时清理远程跟踪分支。默认值为 "false"。

 

remote.<name>.prune

  如果设置为 true,则从该远程仓库执行 fetch 命令时,会自动删除那些在远程仓库已不存在的远程跟踪引用(就像命令行上加了 --prune 选项一样)。会覆盖任何 fetch.prune 的设置。


2
顺便说一下:我刚从这篇文章中了解到了 git config -egit config -e --global。不再需要输入 vim 命令来指向特定路径的 git 配置文件,也不必再考虑那个特定路径是什么了。 - ecbrodie
这个答案非常详细,但由于它的格式很难阅读。我认为只需提供"To always --prune for git fetch and git pull in all your Git repositories: git config --global fetch.prune true"并附上相关文档的链接就足够了。 - Thibaud Colas

21
如果你想在每次fetch时总是进行prune,我建议使用 别名

只需输入git config -e以打开编辑器,并更改特定项目的配置,添加如下部分:

[alias]
pfetch = fetch --prune   

使用git pfetch命令获取代码时,修剪操作将自动执行。


我明白。顺便说一下,拉取操作将使用git fetch而不是git pfetch...那么我应该直接为pull设置别名吗? - Edmondo
1
我会这样做。这样你就有了普通的pullfetch以及它们的修剪版本两个选项。实际上,我认为(但我没有尝试过)你可以直接在别名部分写fetch = fetch --prune,因此pull将自动使用修剪后的fetch - ThanksForAllTheFish
2
据我所知,fetch = fetch --prune 不起作用,使用别名覆盖命令对我也没有用。这可能是因为我使用的是旧版本(1.7.2.5)。 - Uipko
4
根据 git config 文档:“为避免脚本使用时的混淆和问题,隐藏现有 Git 命令的别名将被忽略。” - Dewayne Christensen

2

我最终会将已删除的分支推回去。

如果你的git配置使它推送了你不想推送的分支,这可能会成为一个问题。个人而言,我更喜欢设置它仅在我明确指定要推送的分支时才进行推送。

请参考https://dev59.com/mnNA5IYBdhLWcg3wdtv5#948397,了解如何配置 git 仓库的推送设置。


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