【问题标题】:Not Possible to switch branch after --skip-worktree--skip-worktree 之后无法切换分支
【发布时间】:2015-06-15 10:58:50
【问题描述】:

我想做什么

我有一个包含敏感数据的文件,所以我不想将此文件的内容推送到远程服务器。

我做了什么?

为了实现这一点,我在文件为空时进行了提交,并将这个空文件推送到服务器(GitHub)。然后用敏感数据填充文件并应用 git update-index --skip-worktree path/to/file 。但我没有做出任何承诺。

现在我正在尝试切换我的分支,但我收到了这个错误:

    error: Your local changes to the following files would be overwritten by checkout:
    path/to/file
    Please, commit your changes or stash them before you can switch branches.
    Aborting

为什么我使用skip-worktree 而不是assume-unchanged

我阅读了一些关于这个主题的 SO 问题,并找到了 Borealid's answer

--assume-unchanged 假定开发人员不应该更改文件。此标志旨在提高 SDK 等不更改文件夹的性能。

--skip-worktree 当你指示 git 不要接触特定文件时很有用,因为开发人员应该更改它。例如,如果上游的主存储库托管了一些生产就绪的配置文件,并且您不想意外提交对这些文件的更改,那么 --skip-worktree 正是您想要的。

在这之后,我找到了Jeff's questionVonC's answer。 Jeff 的问题和我的差不多,我跟着 VonC 的解决方案。但是,这对我不起作用。可能是因为 git 版本不同。因为那个问题来自 2012 年。我们与 VonC 进行了交谈,他说这是一个新问题,因为他不记得答案了。

我尝试同时使用--assume-unchanged--skip-worktree,以及软重置工作树。但什么都没有改变。

所以?

你能帮我解决我的问题吗?

谢谢。

【问题讨论】:

  • 我试图重现该问题,但它对我有用。我可以重现它的唯一方法是我的私人文件在我的分支之间是否不同。您是否仔细检查过您的分支之间的path/to/file 是否完全相同?做git diff branch1..branch2 -- path/to/file.
  • @Eray Justin 是对的。您必须确保有问题的文件(在 --skip-worktree 之前)在您的分支中是相同的。
  • 我要补充一点,如果您尝试签出的分支中根本不存在 path/to/file ,也会发生这种情况。因为当您尝试签出时,git 会尝试删除已签出分支中不存在的文件。 “您必须确保所讨论的文件在您的分支中是相同的”这句话暗示了这一点,但我认为最好明确说明

标签: git git-branch git-assume-unchanged git-skip-worktree


【解决方案1】:

我还没有找到一个简洁的解决方案,所以我使用.bat 文件在受影响的文件上运行--no-skip-worktree。然后我stash,切换分支,stash apply,然后使用另一个.bat文件在相同的文件上运行--skip-worktree

这不是很好,但这是我迄今为止找到的最简单和最快的方法。

更新: 我又遇到了这个问题,所以创建了一个 PowerShell 脚本,而不是上面提到的 .bat 文件。它将提示用户是否要跳过或不跳过文件。更新这两个参数,您就可以开始了:

[string]$repoPath = "C:\Fully\Qualified\Path"
[string[]]$filesToSkip = @(
    "Local/Path/To/File.txt",
    "Local/Path/To/OtherFile.txt"
)

$skipText = Read-Host -Prompt 'Skip files? (y/n)'
$skip = $skipText -like "y"
cd $repoPath
foreach ($file in $filesToSkip)
{
    if($skip)
    {
        Write-Host "Skipping" $file
        git update-index --skip-worktree $file
    }
    else
    {
        Write-Host "No-skipping" $file
        git update-index --no-skip-worktree $file
    }
}

【讨论】:

  • 你能分享你的 .bat 文件吗?
  • @Woland 恐怕我没有这个副本了,但如果我没记错的话,每个文件都有一个只包含--no-skip-worktree,另一个只包含--skip-worktree对于相同的文件。
  • @Woland 我刚刚又遇到了这个问题,所以我更新了我的答案并添加了一个可以使用的 PowerShell 脚本
【解决方案2】:

我遇到了同样的问题,归结为我想假设的文件的传入更改 - 未更改。

因此,如果我只是对文件执行 no-assume-unchanged,请将其存储,检查最新版本,弹出我的存储,然后再次假定未更改。

所以现在我可以再次切换分支了。

【讨论】:

  • 这被否决了,但它实际上解释了潜在的问题。上面的解决方案解决了问题,但不要明确说出问题所在 - 这对我有帮助。
【解决方案3】:

你可以enable sparse checkout and add the file there加上skip-worktree标志(如果你单独添加sparse checkout它可能会被删除)。

要排除文件,您应该将其放入 sparse-checkout 文件中(参见git-read-tree 手册):

/*
!unwanted

那么它不会在更新时被触及(所以你不会在那里获得另一个分支的内容,而是保留你的编辑)。这可能不是你想要的。

【讨论】:

    【解决方案4】:

    嗯,这是一个粗糙的解决方案,但似乎工作得相当好(尽管它只是经过轻微测试):

    PATH 的某处创建一个名为git-checkoutsw 的文件,其内容如下:

    #!/bin/bash
    ignored=( $(git ls-files -v | grep "^S " | cut -c3-) )
    for x in "${ignored[@]}"; do
      git update-index --no-skip-worktree -- "$x"
    done
    git checkout -m $@
    for x in "${ignored[@]}"; do
      git update-index --skip-worktree -- "$x"
    done
    

    脚本捕获被忽略文件的列表,取消忽略它们,使用-m(用于合并)和指定的任何其他参数检出新分支,然后再次忽略它们。

    现在您可以使用git checkoutsw 而不是git checkout

    【讨论】:

      【解决方案5】:

      是否有理由签入该文件的空变体?如果没有

      git rm --cached path/to/file
      echo 'path/to/file' >> .gitignore
      git commit -m'stop tracking path/to/file'
      

      可能会解决您的问题。 (对于具有该文件的每个分支都必须重复。或者,如果您不介意历史重写,也可以使用 git filter-branch 在以前的提交中摆脱它。)

      【讨论】:

      • 我推送了文件的空变体,否则包含此sensitivefile.php 和这些文件的其他文件将产生找不到文件错误。所以肯定有sensitivedata.php文件,不管是不是空的。
      • 您是否考虑过在构建过程中简单地创建文件?一个常见的模式是有一个 ./configure 脚本,在某些 IDE 中使用项目之前和完整构建之前,该脚本预计会同时运行。只要它像 touching 一个文件一样无害且(计算上)便宜,那么从 post-checkout hook 调用该脚本可能是值得的。
      【解决方案6】:

      在所有文件上找一行来做 --no-skip-worktree

      git ls-files -v | grep "^S" | cut -c 3- | xargs -L1 git update-index --no-skip-worktree
      

      您可以使用该命令轻松创建一个小 alias.unhideall :)

      【讨论】:

        【解决方案7】:

        到目前为止,--assume-unchanged 和--skip-worktree 不像我发现的那样工作。我的 git 版本是:git version 2.8.4 (Apple Git-73) Stash 是目前唯一可行的方法。

        【讨论】:

        • 根据我的经验,您无法隐藏被忽略的文件
        猜你喜欢
        • 2021-09-30
        • 2018-12-19
        • 2012-06-23
        • 2020-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-23
        • 2021-12-12
        相关资源
        最近更新 更多