为什么git pull总是显示新的分支?

elcex8rz  于 2023-03-28  发布在  Git
关注(0)|答案(9)|浏览(376)

我使用git bash for Windows:

$ git version
git version 1.8.0.msysgit.0

几个月来一切都很好,我已经逐渐习惯了git的工作方式,然后突然间,每次我尝试拉取时,git pull都会检索到一些“新”分支:

me@MYPC /d/Projects/MyProject (master)
$ git pull
From github.com:ClientUsername/RepoName
 * [new branch]      branch1 -> origin/branch1
 * [new branch]      branch2 -> origin/branch2
Already up-to-date.

me@MYPC /d/Projects/MyProject (master)
$ git pull
From github.com:ClientUsername/RepoName
 * [new branch]      branch1 -> origin/branch1
 * [new branch]      branch2 -> origin/branch2
Already up-to-date.

我是否配置错误?这是否正常?

编辑

在一些有用的评论之后,我删除了.git\refs\remotes\origin中的分支文件。我试图再次拉取,得到以下结果:

me@MyPC /d/Projects/MyProject (master)
$ git pull
From github.com:ClientUsername/RepoName
 * [new branch]      Branch1 -> origin/Branch1
 * [new branch]      Branch2 -> origin/Branch2
 * [new branch]      branch1 -> origin/branch1
 * [new branch]      branch2 -> origin/branch2
Already up-to-date.
me@MyPC /d/Projects/MyProject (master)
$ git pull
From github.com:ClientUsername/RepoName
 * [new branch]      Branch1 -> origin/Branch1
 * [new branch]      Branch2 -> origin/Branch2
Already up-to-date.

唯一的区别是分支名称的情况?

bzzcjhmw

bzzcjhmw1#

在我的例子中,这个问题与两个同名的分支有关(一个大写,一个小写)。一旦我从远程源删除了“重复”分支,我运行了以下命令:

git fetch --prune origin

并且[new分支]消息在每次pull之后停止显示。有关prune的文档,请参阅参考资料。

ou6hu8tu

ou6hu8tu2#

有一个类似的问题,问题是与现有的本地文件夹不匹配的名称在远程服务器由于区分大小写的差异。什么工作对我来说是要

.git/refs/remotes/origin

您可以在其中找到受影响的分支文件夹名称,并将其重命名为*[new branch]行中建议的名称,或者将其删除并再次pullpull将在正确的文件系统情况下重新创建文件夹。
虽然从你的最后一次编辑它看起来像在远程服务器上,你有两个文件夹(即Branch1branch1),所以我会仔细检查哪一个是正确的文件夹,并删除远程错误的一个,然后确保文件夹名称是匹配的一个在您的本地。

eaf3rand

eaf3rand3#

我可以通过在.git/packed_refs中列出一个分支 not,并将其在.git/refs/remotes/origin中的文件重命名为相同但不同的大小写来重现这种行为。(在NTFS文件系统上)。
我想如果您可以重命名为与远程名称匹配的表单,这对您来说将是一个修复。
想了想,使用编辑后的第一个表单:
你必须有两个分支类似的名称只是不同的情况下远程!
问题是因为他们想要创建相同的文件。你必须在远程修复它,通过重命名一个类似名称的分支。

np8igboo

np8igboo4#

如您所见:

* [new branch]      Branch1 -> origin/Branch1
* [new branch]      Branch2 -> origin/Branch2
* [new branch]      branch1 -> origin/branch1
* [new branch]      branch2 -> origin/branch2

您有4个分支,它们的名称相同,但大小写不同。这无法在Windows上镜像,因为分支存储为文件,并且您不能在同一个文件夹中拥有两个文件Branch1branch1
要解决这个问题,请通过运行git push origin :Branch1删除其中一个,并对Branch2执行相同的操作。

yftpprvb

yftpprvb5#

我也在运行git for Windows(版本2.20.0.windows.1),也遇到了同样的问题,但在本帖其他答案的帮助下设法解决了这个问题。
在我的例子中,一个新的分支是由一个团队成员添加到一个路径下的,该路径与已经存在的分支不同。
现有的分支机构如下:

feature/branch-1
feature/branch-2

然后创建了一个新的分支:

Feature/branch-3

注意所有分支都有唯一的名称;但是在字feature上情况不同。
git pull上,我收到了一个关于新分支的通知;它为.git\refs\remotes\origin\feature下的创建了一个branch-3文件,分支创建的顺序在这里可能很重要;因为.git\refs\remotes\origin\feature先于.git\refs\remotes\origin\Feature存在;我的路径是小写的。颠倒分支创建的顺序可能会导致大写的Feature路径。
每个后续的git pull都会报告这个新分支。
问题是即使分支的文件存在;分支未添加到.git\packed-refs。修复方法是手动为问题分支添加一行**,并使用正确的大小写**:

# pack-refs with: peeled fully-peeled sorted 
...
<hash> refs/remotes/origin/feature/branch-1
<hash> refs/remotes/origin/feature/branch-2
<hash> refs/remotes/origin/Feature/branch-3
...

其中<hash>取自.git\refs\remotes\origin\feature\branch-3文件。
同样,我们推测最初的问题,假设我有以下分支:

feature/branch-1
feature/Branch-1

Windows会将两个分支的哈希写入单个路径.git\refs\remotes\origin\feature\branch-1(或大写B,取决于分支创建顺序)。
我还打赌.git\packed-refs中只有一个条目用于两个分支。也许为两个分支添加条目将有助于摆脱git pull报告的新分支消息,但如上所述,git checkout feature/branch-1后面跟着git checkout feature/Branch-1可能会很有趣。
希望这对别人有用!

qxsslcnc

qxsslcnc6#

(感谢Paul,与Paul不同,我在Windows上的Cygwin上运行git本地。git remote是Linux服务器。)
每次我做git pull的时候,git建议'someBranchName'时都会出现这个错误:

$ git pull
From <server>:<path>
 * [new branch]        someBranchName -> origin/someBranchName
Already up to date

有两个分支的情况不同:

$ git branch -a | grep -i SomeBranchName
  remotes/origin/someBranchName
  remotes/origin/SomeBranchName

我的做法是编辑.git/refs/remotes/origin/someBranchName(这个文件存在于我的本地仓库中)并获取它的哈希值。然后编辑.git/packed-refs并为两个分支添加第二个具有相同哈希值的条目:

012345ae refs/remotes/origin/someBranchName
012345ae refs/remotes/origin/SomeBranchName
gzjq41n4

gzjq41n47#

同样的事情发生在我身上,并能够解决它。我们在repo中创建的每个分支将被添加到路径.git/refs/remotes/origin。还有另一个fie .git/packed-refs,它维护每个分支的哈希值。
问题来了,文件系统不接受区分大小写的文件夹/文件名。

  1. .git/refs/remotes/origin/Feature.git/refs/remotes/origin/feature
  2. .git/refs/remotes/origin/feature/SampleBranchName.git/refs/remotes/origin/feature/samplebranchname
    在这种情况下,相应的哈希值将不会在.git/packed-refs文件中提及。
    因此,如果将.git/refs/remotes/origin/feature/SampleBranchName文件中分支的哈希值添加到.git/packed-refs列表中,问题就解决了。
hm2xizp9

hm2xizp98#

对我有效的方法很简单:

rm .git/index
git reset
vecaoik1

vecaoik19#

靶区;DR

for i in {1..10}; do git pack-refs --all; git pull; done

这引起了很多挠头,我尽管大部分有用的信息已经在这里。

大小写敏感文件系统

这似乎是不区分大小写的文件系统的一个副作用。当远程仓库文件系统区分大小写而本地仓库不区分大小写时,本地仓库将无法将本地分支与远程分支进行比较,并将其视为 new

不区分大小写文件系统

mkdir bug && ls 
# => bug
mkdir Bug; ls
# => mkdir: Bug: File exists
# => bug

文件系统认为目录“Bug”已经存在,因为它不区分大小写,并认为现有的“bug”目录与“Bug”目录相同。😡
这一点在git中很重要,因为git会将refs或指向特定提交的文件存储在本地硬盘上,并且分支名称中的每个/都会导致创建一个目录。
让我们以两个分支为例:

  • Bug/foo
  • bug/bar

在知道这两个分支的存储库中,您可能会看到以下文件:

  • .git/refs/remotes/origin/Bug/foo
  • .git/refs/remotes/origin/bug/bar

如果文件系统不允许两个不同的子目录“Bug”和“bug”,那么git就会遇到问题。git在执行git pull时会继续保持refs与远程分支的同步,但它也会输出一个警告,说明这是本地仓库第一次看到这个“新”分支。
溶液
执行git pack-refs --all,然后执行git pull,然后重复执行,直到所有警告消失。这将把任何存储为目录和文件的本地引用转换为单个平面文件(.git/packed-refs)。
默认情况下,将新分支拉下为 unpacked,或目录和文件。当你得到一个新分支遇到大小写不匹配时,你必须执行此操作。

演示

下面是一个脚本,试图演示这个问题。
要真正复制这个,您需要创建一个区分大小写的卷(请参阅代码注解)。
如果不想添加或删除卷,请将REMOTE的值更改为REMOTE="${SCRIPT_DIR}/casing-remote"。这不会完全按照预期执行,因为在这种情况下,“远程”存储库只是不区分大小写的文件系统上的另一个目录,因此不可能创建大小写不匹配的两个远程分支。无论哪个目录首先到达远程(“Bug”)都将获胜。
为了完全重现这个问题,我们需要一个区分大小写的远程存储库和一个不区分大小写的本地存储库。

#! /usr/bin/env bash

# WARNING
# These are dangerous commands that create and delete
# disk volumes. Uncomment and execute at your own risk.

# [BEGIN DANGEROUS COMMANDS]
# 
# This is the command to "cleanup" or remove the newly created Volume.
# This will delete the Volume with an id of `disk1s9` that is going to
# change depending on your drive setup. Execute `diskutil list` to see 
# general disk info
#
# `diskutil apfs deleteVolume disk1s9`
#
# Create a case sensitive volume
# `diskutil apfs addVolume disk1 APFSX Casesensitive` # disk1s9
#
# [END DANGEROUS COMMANDS]

SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
REMOTE=/Volumes/Casesensitive/casing
# Set REMOTE="${SCRIPT_DIR}/casing-remote"
# If you do not want to create a case sensitive volume
REPO="${SCRIPT_DIR}/casing-bob"
REPO_OTHER="${SCRIPT_DIR}/casing-alice"

rm -rf "${REPO}" "${REPO_OTHER}" "${REMOTE}" && \
  mkdir "${REPO}" "${REPO_OTHER}" "${REMOTE}" && \
  cd "${REMOTE}" && \
  git init --bare && \
  cd "${REPO}" && \
  git init && \
  echo "#casing" > README.md && \
  git add README.md && \
  git commit -m "init commit" && \
  git branch -M master && \
  git remote add origin "${REMOTE}" && \
  git push -u origin master && \
  git clone "${REMOTE}" "${REPO_OTHER}" && \
  cd "${REPO}" && \
  git checkout -b Bug/foo && \
  touch foo && \
  git add foo && \
  git commit -m "adding foo file" && \
  git push --set-upstream origin Bug/foo && \
  cd "${REPO_OTHER}" && \
  git checkout -b bug/bar && \
  touch bar && \
  git add bar && \
  git commit -m "added bar file" && \
  git push --set-upstream origin bug/bar && \
  cd "${REPO_OTHER}" && \

  # casing-alice always thinks that Bug/foo is a new branch
  # because it has a loacl ref of ".git/refs/remotes/origin/bug/bar"
  # so it doesn't know Bug/foo and bug/foo are the same branch.
  # It does seem that local "bug/foo" 
  # is in sync with remote "Bug/foo" despite the warning

  git pull
  git pull

当使用git branch -r列出每个repo(Bob和Alice)中的远程分支时,问题就很明显了。输出会根据首先创建的 shell 而变化。

casing-bob(git分支-r)
origin/Bug/bar
origin/Bug/foo
origin/master
casing-alice(git分支-r)
origin/HEAD -> origin/master
origin/bug/bar
origin/bug/foo
origin/master
remote(git分支)
Bug/foo
bug/bar
* master

每个repo对实际的远程分支有不同的看法。
我用git打开了一个bug,下面是关键信息
是的,这是一个已知的问题。问题是,Git目前无法在不区分大小写的文件系统上处理像Foo和foo这样的分支。因为分支名称是以文件的形式存储的,而这在Windows或MacOS下通常不能很好地工作。
作为一种变通方法,可以使用git pack-refs。
git bug thread

相关问题