如何配置 Git 以在分支更改时自动从原点拉取?

How do I configure Git to automatically pull from origin on branch change?

当我切换分支时,如果本地是干净的并且落后于其对应的原始分支,我希望始终从原始分支中提取最新的更改。本地分支是其远程分支的跟踪分支,并且 fetch 按预期工作。


编辑:

对于上下文,我使用 Visual Studio 2017,主要是它的用户界面来执行 Git 命令。使 Git 保持最新状态没有问题。我需要使用命令行执行一些 Git 命令,例如重命名分支或隐藏回购设置。

当我说 "local is clean" 时,是的,它指的是来自 git status 的工作树,并且在没有传出提交或本地修改文件的 VS 中。 VS 有一个非常好的 UI 可以实时显示这些信息。

来自

(Our branches are frequently created and deleted as company policy is one branch per task which is PR'd and merged when reviewed)

这应该是一种副手的说法 "I really don't want to set this setting or hook up for every single branch",但解释是:

我们创建自己的本地分支,从主分支中分离出来以完成任务。在 VS 中,这是 "Create local branch from...",它执行具有所需名称的分支的签出。 在幕后,我确信这等同于 git checkout -b fillcatnip masterfillcatnip 是一个未跟踪的本地分支,直到被推送到远程,但它会被推送为一个新分支 fillcatnip 而不是原始 master。那时,它变成了一个跟踪分支,并且可以在任务完成时被给予一个拉取请求(PR)以合并回 master。 但是,如果 master 在 PR 完成之前继续前进并发生冲突,则在解决冲突之前无法合并分支。到这时,我可能已经开始了另一项任务。因此,如果我保存当前正在进行的任务(提交和推送、隐藏等),然后切换回冲突的分支,我想要那个分支的远程副本而不是我自己的本地副本,因为有人可能已经推送了在等待合并时对其进行更改。

您需要 git hook — in your case it's post-checkout hook。在挂钩中调用 git pull.

像这样:

#!/bin/sh

prev_HEAD=""
new_HEAD=""
new_branch=""

if [ "$new_branch" = 1 ]; then
    git pull origin "$new_HEAD"
fi

exit 0

两个问题的答案是"not exactly"和"no",也是"normally there's no need",其实问题本身并没有像问的那么多意义。第一个也是最大的问题在于短语 "if local is clean"——这究竟是什么意思?

如果 "clean" 指的是 git status 报告的内容:

On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working tree clean

然后 "clean" 指的是 work-tree,有时可能指的是 index,相比之下彼此 and/or HEAD 提交。

除非你使用git worktree add创建辅助work-tree,否则任何给定的只有一个 work-tree(和一个相应的索引) Git 存储库。 (如果你 do 使用 git worktree add,每个添加的 work-tree 都是独立的 b运行ch。这实际上可能就是你的答案真的要找,就在这里。)

这里我们还要注意 b运行ch namemasterfeature 表示一个特定的提交,Git 调用那个 b运行ch 的 tip 提交。 "branch" 这个词还有其他含义:请参阅 What exactly do we mean by "branch"? 但是当你签出一个 b运行ch 时,这意味着你有一个特定的 commit 也签出。该提交的内容填充索引和 work-tree.

切换 b运行 或 "detached HEAD" 的命令是 git checkout。它通过写入索引和 work-tree 来完成 branch-switching(或 HEAD-detaching),无论需要什么来实现从之前的 checked-out 提交切换到您现在将拥有 checked-out 的提交。如果 work-tree 在 之前 git checkout 是干净的,这总是可能的,并且 work-tree 将在 [=] 之后是干净的119=] 还有 git checkout

如果 work-tree 在 git checkout 之前 干净,有时但并非总是如此,仍然可以切换 b运行切斯:见 Checkout another branch when there are uncommitted changes on the current branch。在那种情况下,work-tree 通常也会 not-clean 之后 git checkout 已经切换 b运行。 not-clean-ness 是因为在切换 b运行ches 时,结帐不必更新索引和 work-tree 与您的提交不匹配的文件的条目在你 运行 git checkout <em>b运行chname</em>.

之前结帐

正在检查 work-tree 是否干净

完成上述内容后,请注意 git-sh-setup, a script that is available to other Git scripts, includes a function named require_clean_work_tree。您可以检查或简单地使用此代码来确定 work-tree 是否干净。

您可以将它与 结合起来进行检查,如果合适,还可以结合 运行 git mergegit fetch && git merge。 (我建议完全避免 git pull:像这样把它分成两个独立的步骤。之后你的生活会更快乐。)

为什么我怀疑你根本不需要这个

(Our branches are frequently created and deleted as company policy is one branch per task which is PR'd and merged when reviewed)

作为一般规则,如果您不打算在命名的 b运行ch 上工作(在其上进行新提交),您不应该创建首先。没有创建它,你永远不需要担心更新它。

例如,假设您有一个存储库,其中包含一个名为 origin 的远程服务器,并且在 origin 上,有用于各种任务的 b运行 分支。您想偶尔 检查 origin/task/feedkittens,但是 处理 (单个)任务 task/fillcatnip

在这种情况下,要检查东西,继续使用"detached HEAD"模式:

git checkout origin/task/feedkittens

处理事情,使用git checkout创建task/fillcatnip origin/task/fillcatnip:

git checkout task/fillcatnip

这是有效的,因为 git checkout 会在您要求它检查 不存在 的 b运行ch 时搜索 origin/ b运行ch 否则具有相同的名称。如果是这样,它将 创建 本地 b运行ch 使得 b运行ch 提示提交与 remote-tracking 名称的提交相同。同时,它会将本地 b运行ch 设置为 track(作为其上游)名称 remote-tracking。

通过创建本地 b运行ch 名称,您现在可以创建新的提交。这些将使本地 b运行ch

通过避免创建 task/feedkittens,您只需 运行 git fetchgit checkout origin/task/feedkittens 即可查看最新的。您将处于 "detached HEAD" 模式,因此现在创建 new 提交通常不是一个好主意,但这意味着无需拖拽本地 b运行 ch.

当名为 task/feedkittens 的 b运行ch 在 origin 被删除时,您可以在 git fetch 期间自动删除您自己的 remote-tracking 名称设置:

git config fetch.prune true

一旦您 git checkout 某个其他提交或名称,您就不再是 detached-HEAD 在不再有名称的 origin/task/feedkittens 提交上。

如果您想同时处理(如 "add commits to")多个不同的 b运行ches,请考虑使用 git worktree add,只要您的 Git 在最低版本 2.5。每个添加的 work-tree 都有自己的私有索引,但所有添加的 work-tree 共享一个底层存储库。如果您的 Git 太旧,请考虑为您想要同时处理的每个 b运行ch 制作单独的克隆。