如何让远程跟踪分支保持与裸 Git 存储库中的远程源的最新状态?

发布于 2024-10-12 13:53:48 字数 1007 浏览 2 评论 0原文

我正在尝试维护 Git 存储库的裸副本,但在保持远程跟踪分支保持最新状态方面遇到了一些问题。我像这样创建远程跟踪分支:

git branch -t 0.1 origin/0.1

这似乎做了我在该时间点需要做的事情。但是,如果我对 origin 进行更改,然后使用裸存储库进行获取,事情就会开始崩溃。我的工作流程如下所示:

git fetch origin

看起来所有提交都在此时进入,但我的 0.1 本地副本并未更新。我可以通过执行以下操作看到更改已被引入存储库:

git diff 0.1 refs/remotes/origin/0.1

我需要做什么才能使用远程更新更新我的跟踪分支?我觉得我一定在某个地方错过了一步或旗帜。

更新:附加说明

通常,人们会推送到一个裸存储库,而不是从其中运行 git fetch。如果你能安排好这样做,生活就会轻松得多。

以下是对工作流程的一些说明。

该项目的公共 git 存储库托管在 GitHub 上。我正在使用 Redmine 管理项目(wiki、问题、论坛)。 Redmine 需要本地裸存储库才能运行。当 GitHub 收到更改时,它会 ping Redmine。然后,Redmine 尝试从其来源 (GitHub) 获取更改。

如果我只是与 master 一起工作,但它不与我的跟踪分支一起工作,那么这非常有用。正在导入更改,但未在 Redmine 存储库浏览器的分支中列出,因为本地分支未更新。

我确信我可以用另一种方式解决这个问题,但找到一个(通用)解决方案来启动和运行跟踪分支绝对是我的偏好,因为大多数 Redmine 的 git 相关插件都假设“git fetch origin”之类的东西就是全部这是需要做的。

请参阅已接受的答案以获取完整的解决方案。 --mirror 解决方案似乎正是这种情况下所需要的。

I am trying to maintain a bare copy of a Git repository and having some issues keeping the remote tracking branches up to date. I create the remote tracking branches like this:

git branch -t 0.1 origin/0.1

This seems to do what I need to do for that point in time. However, if I make changes to origin and then fetch with the bare repo, things start to fall apart. My workflow looks like this:

git fetch origin

It looks like all of the commits come in at that point, but my local copy of 0.1 is not being updated. I can see that the changes have been brought into the repository by doing the following:

git diff 0.1 refs/remotes/origin/0.1

What do I need to do to get my tracking branch updated with the remote's updates? I feel like I must be missing a step or a flag somewhere.

Updated: Additional Clarification

Normally one would push into a bare repository, rather than run git fetch from within it. If you can arrange to do that, life will be much easier.

Here is a bit of clarification on the workflow.

The project's public git repository is hosted on GitHub. I am managing the project (wiki, issues, forums) using Redmine. Redmine requires a local bare repository in order to operate. When GitHub receives changes it pings Redmine. Redmine then attempts to fetch changes from its origin (GitHub).

This works great if I'm just working with master but it was not working with my tracking branches. The changes were being imported but were not being listed in the branch in Redmine repository browser because the local branches were not being updated.

I'm sure I could have worked this out another way but finding a (generic) solution to getting the tracking branches up and running was definitely my preference as most of the git related plugins for Redmine assume things like "git fetch origin" is all that needs to be done.

See accepted answer for the complete solution. The --mirror solution seems to be exactly what is needed in this case.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

就像说晚安 2024-10-19 13:53:48

通常,人们会推送到一个裸存储库,而不是从其中运行 git fetch 。如果你能安排好这样做,生活就会容易得多。

如果您必须获取而不是推送,并且您只想在裸存储库中创建源镜像,则可以完全避免使用远程跟踪分支。如果您从头开始启动此镜像,Charles Bailey 在下面指出,git 将为您完成所有这些设置如果您最初使用 git clone --mirror 克隆存储库。

否则,您可以获得类似的效果:

git fetch origin +refs/heads/*:refs/heads/*

+ 意味着这将用远程分支的状态覆盖本地分支的状态。如果没有 +,非快进合并的更新将被拒绝。然而,如果这只是一面镜子,那应该没什么问题。 (您可以通过将配置变量 remote.origin.fetch 设置为 +refs/heads/*:refs 来将其配置为 git fetch origin 上的默认操作/heads/*。如果您还想从源镜像标签和远程跟踪分支,则可以使用 +refs/*:refs/*。)

但是,如果,正如您最初询问的那样,您想要维护远程跟踪分支并有选择地将它们合并到本地分支中,您可以使用以下步骤,但我不一定推荐它们,除非您是唯一使用这个裸存储库的人。 (注意:最初在这里我建议使用“git symbolic-ref HEAD refs/heads/whatever”来切换分支并使用“git reset --soft”来更改分支引用 - 但是,Charles Bailey 在评论中指出,可以使用“git update-ref refs/heads/whatever refs/remotes/origin/whatever”,这不需要先切换分支。)

首先,您可能需要检查更新分支是否是快进合并,然后更新分支。请注意,这里存在竞争条件,这就是为什么我说只有当您是唯一使用本地裸存储库的人时才应该执行此操作 - 如果其他人在这些步骤之间的分支上移动,则检查将毫无用处。

  1. 您可以通过比较 git merge-base master origin 来检查等效合并是否是快进(即 origin/master 的历史记录包括 master) /master 和 git show-ref master - 它们应该是相同的。或者您可以使用 这个问题,它通过一些额外的检查来执行这些命令。)
  2. 最后,您可以更新当前分支(在本例中为 master )指向 origin/mastergit update-ref refs/heads/master refs/remotes/origin/master

但是,正如我在一开始所说的,我想您想要的真正解决方案是:

  • 推送到裸存储库或
  • 精确镜像远程裸存储库,正如我上面所描述的,

我希望这有一些用处。

Normally one would push into a bare repository, rather than run git fetch from within it. If you can arrange to do that, life will be much easier.

If you have to fetch rather than push, and you just want to create a mirror of origin in your bare repository, you could avoid having remote-tracking branches entirely. If you're starting this mirror from scratch, Charles Bailey points out below that git will do all of this setup for you if you initially clone the repository with git clone --mirror.

Otherwise, you could get a similar effect with:

git fetch origin +refs/heads/*:refs/heads/*

The + means that this will overwrite the state of your local branches with those from the remote. Without the +, updates that aren't fast-forward merges will be rejected. However, if this is just a mirror, that shouldn't matter. (You can configure this to be the default action on git fetch origin by setting the config variable remote.origin.fetch to +refs/heads/*:refs/heads/*. If you want to mirror tags and remote-tracking branches from origin as well, you could use +refs/*:refs/* instead.)

However, if, as you originally ask, you want to maintain remote-tracking branches and selectively merge them into local branches, you can use the following steps, but I don't necessarily recommend them unless you're the only person using this bare repository. (Note: originally here I suggested using "git symbolic-ref HEAD refs/heads/whatever" to switch branch and "git reset --soft" to change the branch ref - however, Charles Bailey pointed out in the comments out that one can use "git update-ref refs/heads/whatever refs/remotes/origin/whatever", which doesn't require one to switch branch first.)

First, you might want to check that updating the branch would have been a fast-forward merge, and after that update the branch. Note that there is a race condition here, which is why I say you should only do this if you are the only person using your local bare repository - the check would be useless if someone else moves on the branch between those steps.

  1. You can check that an equivalent merge would be a fast-forward (i.e. that the history of origin/master includes master) by comparing git merge-base master origin/master with git show-ref master - they should be the same. Or you could use the is-ancestor script in this question, which does those commands with some additional checks.)
  2. Finally, you can update your current branch (master in this case) to point to origin/master with git update-ref refs/heads/master refs/remotes/origin/master

However, as I said at the beginning, I imagine that the real solution you want is either:

  • Pushing into your bare repository instead or
  • Mirroring the remote bare repository exactly, as I described above

I hope that's of some use.

自控 2024-10-19 13:53:48

当您获取时,远程更改会更新您自己的远程本地引用,origin/0.1(这永远不会导致任何冲突,因为origin/0.1 > 从不托管任何本地更改)。要导入这些更改,您可以从 0.1git reset refs/remotes/origin/0.1 ,这将使 HEAD 分支 (0.1) 指向与远程分支相同的提交。

请注意,这样做您将丢失所有非来自远程的 0.1 更改。

When you fetch, remote changes are updating your own local reference for the remote, origin/0.1 (this never causes any conflicts, since origin/0.1 never hosts any local changes). To import those changes, you can git reset refs/remotes/origin/0.1 from 0.1, which will make the HEAD branch (0.1) point to the same commit as the remote branch.

Note that by doing so you will lose any changes to 0.1 not coming from the remote.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文