如何解决 git 远程分支跟踪不一致问题?

发布于 2025-01-10 05:42:36 字数 2524 浏览 0 评论 0原文

我有一个 git 存储库,它似乎对其分支跟踪配置感到困惑,我需要一些帮助来理顺它。我正在运行 git 版本 2.21.0.windows.1

问题是 gitbranch -a 仍然列出了我删除的远程,并且它显示的分支跟踪与 gitremote-v 和 gitremoteshoworigin 不一致。以下是显示存储库当前状态的命令:

C:\dev> git branch -a
* dev-mdbootstrap
  master
  remotes/localrepo/HEAD -> localrepo/master
  remotes/localrepo/dev-mdbootstrap
  remotes/localrepo/master
  remotes/origin/master


C:\dev> git remote -v
origin  https://github.com/MyOrganization/MyProject.git (fetch)
origin  https://github.com/MyOrganization/MyProject.git (push)


C:\dev> git remote show origin
* remote origin
  Fetch URL: https://github.com/MyOrganization/MyProject.git
  Push  URL: https://github.com/MyOrganization/MyProject.git
  HEAD branch: master
  Remote branches:
    dev-mdbootstrap tracked
    master          tracked
  Local branches configured for 'git pull':
    dev-mdbootstrap merges with remote dev-mdbootstrap
    master          merges with remote master
  Local refs configured for 'git push':
    dev-mdbootstrap pushes to dev-mdbootstrap (up to date)
    master          pushes to master          (up to date)


C:\dev> git ls-remote origin
2ac96d0912e126f5ccaafef66133e3fbc3f23f1d        HEAD
bd3366870b7c6848c7d182e971307b9a74e0ae48        refs/heads/dev-mdbootstrap
2ac96d0912e126f5ccaafef66133e3fbc3f23f1d        refs/heads/master

我很困惑为什么 gitbranch -a 仍然列出了 localrepo 并且不显示本地分支 dev- mdbootstrap 跟踪remotes/origin/dev-mdbootstrap

需要对该存储库的历史进行解释。

我最初克隆了一个本地 git 存储库,创建了一个名为 dev-mdbootstrap 的新分支,然后开始工作。因此,此时origin本地 存储库。

后来,我想将现有的 github.com 存储库配置为 origin,因此我执行了以下操作:

C:\dev> git remote rename origin localrepo

C:\dev> git remote add -t master origin https://github.com/MyOrganization/MyProject.git

所有这些似乎都工作得很好。 (https://github.com/MyOrganization/MyProject.git 远程以前仅包含master 分支。)

我将本地 dev-mdbootstrap 分支推送到新配置的 GitHub origin 存储库:

C:\dev> git push -u origin dev-mdbootstrap:dev-mdbootstrap
Counting objects: 100% (59/59), done.
[...snipped...]
Branch 'dev-mdbootstrap' set up to track remote branch 'dev-mdbootstrap' from 'origin'.

最终,我决定删除localrepo 存储库:

git remote rm localrepo

我很困惑为什么 git Branch -a 仍然显示 localrepo。我怎样才能把它弄直?

谢谢!

I have a git repository that seems to be confused about its branch tracking configuration, and I need some help straightening it out. I'm running git version 2.21.0.windows.1.

The problem is that git branch -a still lists a remote I deleted, and it shows branch tracking that is inconsistent with git remote -v and git remote show origin. Below are commands showing the current state of the repo:

C:\dev> git branch -a
* dev-mdbootstrap
  master
  remotes/localrepo/HEAD -> localrepo/master
  remotes/localrepo/dev-mdbootstrap
  remotes/localrepo/master
  remotes/origin/master


C:\dev> git remote -v
origin  https://github.com/MyOrganization/MyProject.git (fetch)
origin  https://github.com/MyOrganization/MyProject.git (push)


C:\dev> git remote show origin
* remote origin
  Fetch URL: https://github.com/MyOrganization/MyProject.git
  Push  URL: https://github.com/MyOrganization/MyProject.git
  HEAD branch: master
  Remote branches:
    dev-mdbootstrap tracked
    master          tracked
  Local branches configured for 'git pull':
    dev-mdbootstrap merges with remote dev-mdbootstrap
    master          merges with remote master
  Local refs configured for 'git push':
    dev-mdbootstrap pushes to dev-mdbootstrap (up to date)
    master          pushes to master          (up to date)


C:\dev> git ls-remote origin
2ac96d0912e126f5ccaafef66133e3fbc3f23f1d        HEAD
bd3366870b7c6848c7d182e971307b9a74e0ae48        refs/heads/dev-mdbootstrap
2ac96d0912e126f5ccaafef66133e3fbc3f23f1d        refs/heads/master

I'm stumped as to why git branch -a still lists localrepo and does not show local branch dev-mdbootstrap tracking remotes/origin/dev-mdbootstrap.

An explanation of the history of this repository is needed.

I originally cloned a local git repository, created a new branch named dev-mdbootstrap, and began working. So at that point origin was the local repository.

Later, I wanted to configure an existing github.com repository as origin, so I did the following:

C:\dev> git remote rename origin localrepo

C:\dev> git remote add -t master origin https://github.com/MyOrganization/MyProject.git

All of this seemed to work just fine. (The https://github.com/MyOrganization/MyProject.git remote previously contained only the master branch.)

I pushed the local dev-mdbootstrap branch to the newly configured GitHub origin repo:

C:\dev> git push -u origin dev-mdbootstrap:dev-mdbootstrap
Counting objects: 100% (59/59), done.
[...snipped...]
Branch 'dev-mdbootstrap' set up to track remote branch 'dev-mdbootstrap' from 'origin'.

Eventually, I decided to remove the localrepo repository:

git remote rm localrepo

I'm very puzzled why git branch -a still shows localrepo. How can I straighten it out?

Thanks!

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

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

发布评论

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

评论(3

明月松间行 2025-01-17 05:42:36

在 Git 内部,远程跟踪名称的存在(以及存储的值)与远程本身是否存在无关。也就是说,它们只是符合 refs/remotes/r/name 模式的文本字符串,其中 r< /code>是远程名称,name 是在该远程找到的分支名称。

用于更新遥控器的 git remote 命令(addrenamerm应该< /em> 管理适当子命名空间中的远程跟踪名称。因此,当您运行 git Remote rm localrepo 时,这应该会删除所有 refs/remotes/localrepo/* 名称。显然没有;追踪为什么没有发生——错误在哪里——需要一个重现器。

您可以使用低级“管道”命令 git update-ref 手动删除每个“坏”名称,该命令绕过所有正常机制并直接进入 Git 内部:

git update-ref -d refs/remotes/localrepo/HEAD
git update-ref -d refs/remotes/localrepo/dev-mdbootstrap
git update-ref -d refs/remotes/localrepo/master

我们可能永远不会知道为什么 git Remote rm 没有在此处自行清理。

(我怀疑您可能已将 origin 设置为单分支远程。检查:

 git config --get-all remote.origin.fetch

输出通常应该是单行:

+refs/heads/*:refs/remotes/origin/*

任何其他内容都表明设置不正常。不一定错误,只是不寻常。)

Internally in Git, the existence (and stored values of) remote-tracking names are independent of whether the remote itself even exists. That is, they are just text strings that fit the refs/remotes/r/name pattern, where r is a remote-name and name is a branch-name as found on that remote.

The git remote commands that update remotes—add, rename, and rm—are supposed to manage the remote-tracking names in the appropriate sub-namespace. So when you ran git remote rm localrepo, this should have erased all the refs/remotes/localrepo/* names. Apparently it didn't; tracking down why it didn't—where the bug is—would require a reproducer.

You can manually remove each "bad" name using the low-level "plumbing" command git update-ref, which bypasses all the normal mechanisms and goes straight into the Git internals:

git update-ref -d refs/remotes/localrepo/HEAD
git update-ref -d refs/remotes/localrepo/dev-mdbootstrap
git update-ref -d refs/remotes/localrepo/master

We'll probably never know why git remote rm did not clean up after itself here.

(I suspect you might have set up origin as a single-branch remote though. Check with:

 git config --get-all remote.origin.fetch

The output should normally be a single line:

+refs/heads/*:refs/remotes/origin/*

Anything else indicates an unusual setup. Not necessarily wrong, just unusual.)

黑色毁心梦 2025-01-17 05:42:36

您尝试运行 git prune 吗?

git remote prune origin

您可以使用 --dry-run 来查看哪些分支将被修剪

git remote prune origin --dry-run

Did you try to run git prune?

git remote prune origin

You can use --dry-run to see what branches will be pruned

git remote prune origin --dry-run
情深缘浅 2025-01-17 05:42:36

@torek 让我走上了正确的道路。非常感谢!不过,完整的清理工作涉及更多,所以我想记录下来,以防它对某人有帮助。 (请注意,因为我不确定我是否走在正确的道路上,所以在继续之前我对我的 .git 存储库文件夹进行了完整备份。)

从我在中注意到的这个混乱的分支配置开始最初的问题:

C:\dev> git branch -a
* dev-mdbootstrap
  master
  remotes/localrepo/HEAD -> localrepo/master
  remotes/localrepo/dev-mdbootstrap
  remotes/localrepo/master
  remotes/origin/master

根据@torek的指导,我跑了:

C:\dev> git update-ref -d refs/remotes/localrepo/HEAD
C:\dev> git update-ref -d refs/remotes/localrepo/dev-mdbootstrap
C:\dev> git update-ref -d refs/remotes/localrepo/master

这导致了以下结果。请注意忽略损坏的引用警告消息:

C:\dev> git branch -a
warning: ignoring broken ref refs/remotes/localrepo/HEAD
* dev-mdbootstrap
  master
  remotes/origin/master

我摸索着试图解决这个问题。首先,我按照@torek的建议重新检查了git config。查看 git config --get-all ...:

C:\dev> git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/localrepo/*
+refs/heads/dev-mdbootstrap:refs/remotes/origin/dev-mdbootstrap

由于 localrepo 仍然出现在配置中,并且我不确定具体的 git config ... 命令会清理它,我只需运行 git config -e 来在文本编辑器中编辑 .git\config 文件。最初,该文件包含:

[core]
    ...various settings... snipped out...

[remote "origin"]
    url = https://github.com/MyOrganization/MyProject.git
    fetch = +refs/heads/*:refs/remotes/localrepo/*
    fetch = +refs/heads/dev-mdbootstrap:refs/remotes/origin/dev-mdbootstrap
[branch "dev-mdbootstrap"]
    remote = origin
    merge = refs/heads/dev-mdbootstrap
[branch "master"]
    remote = origin
    merge = refs/heads/master

我将 [remote "origin"] 部分简化为以下内容,并保留其他所有内容不变:

[remote "origin"]
    url = https://github.com/MyOrganization/MyProject.git
    fetch = +refs/heads/*:refs/remotes/origin/*

但是,这对 gitbranch -a 没有影响代码>输出。

我直接检查了 C:\dev\.git\refs\remotes 文件夹。它包含一个 origin 和一个 localrepo 文件夹。后者包含一个名为 HEAD 的文件,其内容如下:

ref: refs/remotes/localrepo/master

我四处寻找一种使用 git update-ref -d ... 命令清除此内容的方法,但是我尝试的任何方法都不起作用,所以我最终手动删除了“C:\dev.git\refs\remotes\localrepo”文件夹。

这有帮助!在 gitbranch-agitbranch-vv 返回以下内容之后:

git branch -a
* dev-mdbootstrap
  master
  remotes/origin/master

PS C:\dev> git branch -vv
* dev-mdbootstrap bd336687 [origin/dev-mdbootstrap: gone] ...snipped commit message #1...
  master          2ac96d09 [origin/master] ...snipped commit message #1...

但是为什么显示“origin/dev-mdbootstrap: gone” ?我尝试了 git remote show origin,它返回了以下内容。请注意dev-mdbootstrap new(下次获取将存储在remotes/origin中)行。

C:\dev> git remote show origin
* remote origin
  Fetch URL: https://github.com/MyOrganization/MyProject.git
  Push  URL: https://github.com/MyOrganization/MyProject.git
  HEAD branch: master
  Remote branches:
    dev-mdbootstrap new (next fetch will store in remotes/origin)
    master          tracked
  Local branches configured for 'git pull':
    dev-mdbootstrap merges with remote dev-mdbootstrap
    master          merges with remote master
  Local refs configured for 'git push':
    dev-mdbootstrap pushes to dev-mdbootstrap (up to date)
    master          pushes to master          (up to date)

看来,在我的 git 配置被打乱期间,我之前的命令(例如 git fetch origin dev-mdbootstrap 等)试图强制本地 dev-mdbootstrap 分支track origin/dev-mdbootstrap 根本没有效果。

但由于 git 指示需要 next fetch ,我运行:

C:\dev> git fetch origin
From https://github.com/MyOrganization/MyProject
 * [new branch]        dev-mdbootstrap -> origin/dev-mdbootstrap

然后:

C:\dev> git branch --set-upstream-to=origin/dev-mdbootstrap dev-mdbootstrap
Branch 'dev-mdbootstrap' set up to track remote branch 'dev-mdbootstrap' from 'origin'.

最后, 'gitbranch -a -vv' 返回:

C:\dev> git branch -a -vv
* dev-mdbootstrap                bd336687 [origin/dev-mdbootstrap] ...snipped commit message #1...
  master                         2ac96d09 [origin/master] ...snipped commit message #2...
  remotes/origin/dev-mdbootstrap bd336687 ...snipped commit message #1...
  remotes/origin/master          2ac96d09 ...snipped commit message #2...

现在一切看起来都很干净,并且 git 是表现得像我通常期望的那样。再次感谢 @torek 让我走上正确的道路。这可能不是解决此问题的最佳或最正确的方法,但它完成了工作。

@torek set me on the right course. Thanks much! The full cleanup got more involved though, so I wanted to document it in case it helps someone. (Note that, because I was not sure if I was going down the right path, I made a complete backup of my .git repo folder before proceeding.)

Starting from this scrambled branch configuration that I noted in the original question:

C:\dev> git branch -a
* dev-mdbootstrap
  master
  remotes/localrepo/HEAD -> localrepo/master
  remotes/localrepo/dev-mdbootstrap
  remotes/localrepo/master
  remotes/origin/master

Per @torek's guidance, I ran:

C:\dev> git update-ref -d refs/remotes/localrepo/HEAD
C:\dev> git update-ref -d refs/remotes/localrepo/dev-mdbootstrap
C:\dev> git update-ref -d refs/remotes/localrepo/master

This resulted in the following. Note the ignoring broken ref warning message:

C:\dev> git branch -a
warning: ignoring broken ref refs/remotes/localrepo/HEAD
* dev-mdbootstrap
  master
  remotes/origin/master

I fumbled forward trying to resolve this. First I reexamined git config, following @torek's suggestion. Looking at git config --get-all ...:

C:\dev> git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/localrepo/*
+refs/heads/dev-mdbootstrap:refs/remotes/origin/dev-mdbootstrap

Since localrepo still showed up in the config and I was not sure what individual git config ... commands would clean it up, I simply ran git config -e to edit the .git\config file in my text editor. Originally, the file contained:

[core]
    ...various settings... snipped out...

[remote "origin"]
    url = https://github.com/MyOrganization/MyProject.git
    fetch = +refs/heads/*:refs/remotes/localrepo/*
    fetch = +refs/heads/dev-mdbootstrap:refs/remotes/origin/dev-mdbootstrap
[branch "dev-mdbootstrap"]
    remote = origin
    merge = refs/heads/dev-mdbootstrap
[branch "master"]
    remote = origin
    merge = refs/heads/master

I simplified the [remote "origin"] section to the following, and left everything else unchanged:

[remote "origin"]
    url = https://github.com/MyOrganization/MyProject.git
    fetch = +refs/heads/*:refs/remotes/origin/*

However, this had no impact on the git branch -a output.

I inspected C:\dev\.git\refs\remotes folder directly. It contained both an origin and a localrepo folder. The latter contained a single file named HEAD with the contents:

ref: refs/remotes/localrepo/master

I poked around for a way to clear this out using a git update-ref -d ... command, but nothing I tried worked, so I finally just deleted the ``C:\dev.git\refs\remotes\localrepo` folder manually.

This helped! After this git branch -a and git branch -vv returned the following:

git branch -a
* dev-mdbootstrap
  master
  remotes/origin/master

PS C:\dev> git branch -vv
* dev-mdbootstrap bd336687 [origin/dev-mdbootstrap: gone] ...snipped commit message #1...
  master          2ac96d09 [origin/master] ...snipped commit message #1...

But why did this show "origin/dev-mdbootstrap: gone"? I tried git remote show origin, which returned the following. Note the line dev-mdbootstrap new (next fetch will store in remotes/origin).

C:\dev> git remote show origin
* remote origin
  Fetch URL: https://github.com/MyOrganization/MyProject.git
  Push  URL: https://github.com/MyOrganization/MyProject.git
  HEAD branch: master
  Remote branches:
    dev-mdbootstrap new (next fetch will store in remotes/origin)
    master          tracked
  Local branches configured for 'git pull':
    dev-mdbootstrap merges with remote dev-mdbootstrap
    master          merges with remote master
  Local refs configured for 'git push':
    dev-mdbootstrap pushes to dev-mdbootstrap (up to date)
    master          pushes to master          (up to date)

It seems that during the time my git configuration was scrambled, my earlier commands such as git fetch origin dev-mdbootstrap and others to try to force the local dev-mdbootstrap branch to track origin/dev-mdbootstrap were simply having no effect.

But since git indicated a next fetch was needed, I ran:

C:\dev> git fetch origin
From https://github.com/MyOrganization/MyProject
 * [new branch]        dev-mdbootstrap -> origin/dev-mdbootstrap

and then:

C:\dev> git branch --set-upstream-to=origin/dev-mdbootstrap dev-mdbootstrap
Branch 'dev-mdbootstrap' set up to track remote branch 'dev-mdbootstrap' from 'origin'.

Finally, 'git branch -a -vv' returns:

C:\dev> git branch -a -vv
* dev-mdbootstrap                bd336687 [origin/dev-mdbootstrap] ...snipped commit message #1...
  master                         2ac96d09 [origin/master] ...snipped commit message #2...
  remotes/origin/dev-mdbootstrap bd336687 ...snipped commit message #1...
  remotes/origin/master          2ac96d09 ...snipped commit message #2...

Now everything looks clean, and git is behaving as I normally expect it to. Again, props to @torek for setting me on the right course. This may not be the optimal or most correct way to fix this, but it got the job done.

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