如何让远程跟踪分支保持与裸 Git 存储库中的远程源的最新状态?
我正在尝试维护 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
通常,人们会推送到一个裸存储库,而不是从其中运行 git fetch 。如果你能安排好这样做,生活就会容易得多。
如果您必须获取而不是推送,并且您只想在裸存储库中创建源镜像,则可以完全避免使用远程跟踪分支。如果您从头开始启动此镜像,Charles Bailey 在下面指出,git 将为您完成所有这些设置如果您最初使用 git clone --mirror 克隆存储库。
否则,您可以获得类似的效果:
+
意味着这将用远程分支的状态覆盖本地分支的状态。如果没有+
,非快进合并的更新将被拒绝。然而,如果这只是一面镜子,那应该没什么问题。 (您可以通过将配置变量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”,这不需要先切换分支。)
首先,您可能需要检查更新分支是否是快进合并,然后更新分支。请注意,这里存在竞争条件,这就是为什么我说只有当您是唯一使用本地裸存储库的人时才应该执行此操作 - 如果其他人在这些步骤之间的分支上移动,则检查将毫无用处。
origin/master
的历史记录包括master
) /master 和 git show-ref master - 它们应该是相同的。或者您可以使用 这个问题,它通过一些额外的检查来执行这些命令。)master
)指向origin/master
与git 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:
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 ongit fetch origin
by setting the config variableremote.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.
origin/master
includesmaster
) by comparinggit merge-base master origin/master
withgit show-ref master
- they should be the same. Or you could use theis-ancestor
script in this question, which does those commands with some additional checks.)master
in this case) to point toorigin/master
withgit 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:
I hope that's of some use.
当您
获取
时,远程更改会更新您自己的远程本地引用,origin/0.1
(这永远不会导致任何冲突,因为origin/0.1
> 从不托管任何本地更改)。要导入这些更改,您可以从0.1
中git 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, sinceorigin/0.1
never hosts any local changes). To import those changes, you cangit reset refs/remotes/origin/0.1
from0.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.