为什么git会一直显示新的分支?

Spi*_*keh 27 git

我在Windows上使用git bash:

$ git version
git version 1.8.0.msysgit.0
Run Code Online (Sandbox Code Playgroud)

几个月来一切都运行良好,我已经逐渐习惯了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.
Run Code Online (Sandbox Code Playgroud)

我配置错误了吗?这是正常的行为吗?


编辑

在一些有用的评论之后,我从.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.
Run Code Online (Sandbox Code Playgroud)

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

小智 18

在我的例子中,问题与两个具有相同名称的分支(一个大写,一个小写)有关.一旦我从远程源删除了"重复"分支,我运行以下内容:

git fetch --prune origin
Run Code Online (Sandbox Code Playgroud)

并且每次拉动后[new branch]消息停止显示.有关修剪的文档,请参阅参考.

  • 谢谢,这就像一个魅力。根据文档 --prune:“在获取之前,删除远程上不再存在的任何远程跟踪引用。” 它不仅删除了遥控器上不再存在的远程跟踪引用,还修复了大写小写名称不匹配的问题。 (2认同)

Bal*_*Pal 10

我可以通过在.git/packed_refs中没有列出分支并将.git/refs/remotes/origin中的文件重命名为相同但不同的情况来重现该行为.(在NTFS文件系统上).它通过重命名来治愈.

猜猜你是否可以重命名为与远程名称匹配的表单,这将是一个修复程序.

更多思考,并在编辑后使用第一个表单:

你必须有两个名字相似的分支,只是在远程的情况下不同!

问题是因为他们想要创建相同的文件.您必须通过重命名其中一个类似名称的分支来修复它.


Wal*_*r R 8

有一个类似的问题,问题是由于区分大小写的差异,现有的本地文件夹与远程服务器中的名称不匹配。对我有用的是

.git/refs/remotes/origin
Run Code Online (Sandbox Code Playgroud)

您可以在其中找到受影响的分支文件夹名称并将其重命名为该*[new branch]行中建议的名称或删除它,然后pull再次pull在正确的文件系统案例中重新创建该文件夹。

尽管从您上次编辑看起来在远程服务器中您有两个文件夹(即Branch1branch1),因此我将仔细检查哪个是正确的文件夹并删除远程错误的文件夹,然后确保文件夹名称与您的文件夹名称匹配当地的。


Chr*_*ial 6

正如你在这里看到的:

* [new branch]      Branch1 -> origin/Branch1
* [new branch]      Branch2 -> origin/Branch2
* [new branch]      branch1 -> origin/branch1
* [new branch]      branch2 -> origin/branch2
Run Code Online (Sandbox Code Playgroud)

您有4个分支,并且它们的对具有相同的名称,具有不同的大写/小写.这不能在Windows上镜像,因为分支存储为文件,并且您不能拥有两个文件Branch1并且branch1位于同一文件夹中.

要解决这个问题,请通过运行git push origin :Branch1并删除其中一个来删除其中一个Branch2.


sdc*_*sdc 6

长话短说

for i in {1..10}; do git pack-refs --all; git pull; done
Run Code Online (Sandbox Code Playgroud)

尽管大多数有用的信息已经在这里,但这还是让我很头疼。

区分大小写的文件系统

这似乎是不区分大小写的文件系统的副作用。当远程存储库文件系统区分大小写而本地存储库不区分大小写时,本地存储库无法将本地分支与远程分支进行比较并认为它们是新的

不区分大小写的文件系统

mkdir bug && ls 
# => bug
mkdir Bug; ls
# => mkdir: Bug: File exists
# => bug
Run Code Online (Sandbox Code Playgroud)

文件系统认为目录“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,但它也会输出一条警告,表明这是本地存储库第一次看到这个“新”分支。

解决方案

git pack-refs --all然后执行git pull,然后重复,直到所有警告消失。这会将存储为目录和文件的任何本地引用转换为单个平面文件 ( .git/packed-refs)。

默认是将新分支拉下来作为解压的,或者作为目录和文件。每当您获得遇到大小写不匹配的新分支时,您都必须执行此操作。

演示

这是一个尝试演示该问题的脚本。

要真正复制此内容,您将需要创建一个区分大小写的卷(请参阅代码注释)。

如果您不想添加或删除卷,请将值更改REMOTEREMOTE="${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
Run Code Online (Sandbox Code Playgroud)

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

外壳鲍勃(git分支-r)

origin/Bug/bar
origin/Bug/foo
origin/master
Run Code Online (Sandbox Code Playgroud)

外壳-alice (git 分支 -r)

origin/HEAD -> origin/master
origin/bug/bar
origin/bug/foo
origin/master
Run Code Online (Sandbox Code Playgroud)

远程(git 分支)

Bug/foo
bug/bar
* master
Run Code Online (Sandbox Code Playgroud)

每个存储库对实际远程分支都有不同的看法。

我用 git 打开了一个 bug。这是关键信息

是的,这是[一个已知的陷阱]。问题是,Git 目前无法处理不区分大小写的文件系统上的 Foo 和 foo 等分支。因为分支名称存储为文件,这通常在 Windows 或 MacO 下不能很好地工作。

作为解决方法,可以使用 git pack-refs。

git bug 线程