gpt4 book ai didi

git stash 恢复已删除和重命名文件的索引状态

转载 作者:IT王子 更新时间:2023-10-29 00:49:12 24 4
gpt4 key购买 nike

当暂存已删除或重命名的文件,然后取消暂存它们时,它们将恢复为已删除和未删除状态。

在下面的例子中状态:

$ git status s

A file0
D file1
R file2 -> file3
?? file4

运行 git stash push -k -u 然后 git stash pop --index 将使我处于以下状态:

$ git status s

A file0
D file1
R file2 -> file3
?? file1
?? file2
?? file4

我希望以原始状态结束,删除的文件不会在 pop 之后重新显示为未跟踪。

有什么办法解决这个问题吗?

编辑:这是一个重现问题的脚本(在 Mac OS X 10.13.2 和 git 2.16.1 上测试)

#!/usr/bin/env bash

echo -e "\nInitializing a fresh git dir..."
mkdir gitStashIssue && cd $_
rm -rf * .*
git init


echo -e "\nPreparing git state for test..."
# Create files and commit them
echo 'abc' > file1
echo 'aabbcc' > file2
echo 'aaabbbccc' > file3
echo 'aaaabbbbcccc' > file4
git add .
git commit -m 'initial commit'

# Make changes and add them to stage
echo `cat file1` >> file1
echo `cat file2` >> file2
git add .

# Make another change to a staged file without
# staging it, making it partially staged
echo `cat file1` >> file1

# Delete and rename files
git rm file3
git mv file4 fileRenamed

# Add untracked file
echo "untracked" > untrackedFile

# git status -s should now show
# MM file1
# M file2
# D file3
# R file4 -> fileREnamed
# ?? untrackedFile

echo -e "\nCurrent git status is:"
git status -s

echo -e "\nStasing changes..."
git stash save -u -k

# git status -s should now show
# M file1
# M file2
# D file3
# R file4 -> fileREnamed
# ?? file3
# ?? file4

echo -e "\ngit status after stashing files is:"
git status -s

echo -e "\ncleaning up deleted and renamed files..."
git clean ./ -f

echo -e "\ngit status after cleanup:"
git status -s

echo -e "\nCommiting unstashed changes..."
git commit -m 'commit unstashed changes'

# This causes a conflict in file1
# git status -s should now show
# UU file1
# ?? untrackedFile
git stash pop --index

echo -e "\ngit status after unstashing:"
git status -s

最佳答案

记住:git 不跟踪文件重命名。它跟踪文件内容。

当索引包含对具有相同内容的不同文件的删除和创建时,git 的重命名检测将(可能)断定这是重命名,并有助于将其显示为重命名。不过,这实际上并没有改变索引中的内容。 “真正”发生的确实是先删除后创建,git 只是试图更有帮助地显示它。

自己试试:

$ cp file1 boink
$ rm file1
$ git add .
$ git status

效果相同:

$ git mv file1 boink
$ git status

此重命名检测仅适用于已添加到索引中的内容。现在执行 git reset 你就会明白我的意思了:

$ git reset
$ git status
Changes not staged for commit:
deleted: file1

Untracked files:
boink

我们可以使用 git 命令 git ls-files 列出索引中存在的文件。实际上,这些是 git 目前认为存在的文件。当我们像上面那样重命名时,输出是:

# git ls-files
boink
file2
file3
file4

就索引而言,file1已经不存在了。我们删除了它,然后我们创建了 boinkgit status 很友好,它向我们展示了重命名检测的结果,但请记住,索引并不关心这些。

现在我们运行 git stash -k -u-k 告诉 stash 不要触及索引,所以它不会。考虑一下 stash 联机帮助页的第一段:

Use git stash when you want to record the current state of the working directory and the index, but want to go back to a clean working directory. The command saves your local modifications away and reverts the working directory to match the HEAD commit.

因此:我们要求 stash 保存我们的本地修改(不触及索引),并恢复工作目录以匹配 HEAD 提交。file1 存在于 HEAD 提交中,所以它回来了。但是 file1 不再在索引中,因为我们删除了它。因此,file1 现在是一个未跟踪的文件。由于我们没有触及索引,因此新文件 boink 和它是 file1 重命名结果的记录保留在索引中。因此,您可以从 git status 获得可能令人惊讶的输出:

Changes to be committed:    
renamed: file1 -> boink

Untracked files:
file1

关于git stash 恢复已删除和重命名文件的索引状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48446845/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com