71

我有一个大型 git 项目,我愚蠢地导入了 eclipse 并在其上运行了自动格式化。现在,项目中的每个文件都显示为已修改。与其提交我的格式化文件,我宁愿还原所有我只被格式化并且没有其他更改的文件。例如:

$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#   (commit or discard the untracked or modified content in submodules)

#     modified: dir/file1.cpp
#     modified: dir/file1.h
#     modified: dir/file2.cpp
#     modified: dir/file2.h
#     modified: dir/file3.cpp
#     modified: dir/file3.h
#     modified: dir/file4.cpp
#     modified: dir/file4.h

我知道file2.cpp, file2.h, 并且file3.cpp已经修改了内容(即,不仅仅是格式化)。我想存储对这三个文件的更改,然后签出旧版本,以便之后我可以重新应用对这些文件的更改。我宁愿避免这样的事情:

$ cp file2.cpp ~/tmp
$ git checkout blahblahblah
$ cp ~/tmp/file2.cpp .

如果有一种明显的方法可以做到这一点而不涉及隐藏,请告诉我。什么都能完成工作。

4

5 回答 5

68

您可以add保留要保留更改的文件,然后stash是其余文件并清除存储:

git add file2.cpp file2.h file3.cpp
git stash --keep-index

此时,您已经隐藏了不需要的更改。如果您想永久摆脱它们,请运行:

git stash drop

现在你有file2.cpp, file2.h, 和file3.cppstaged 提交。如果您想存储这些文件(而不是提交它们):

git reset
git stash

现在您将处于您之前的提交中,只隐藏了这三个文件。

更新:

正如 VonC 在他的回答中解释的那样git stash push,Git 2.13 及更高版本包括一种更直接的方式来存储特定文件。

于 2012-09-06T17:21:44.420 回答
65

我知道file2.cpp, file2.h, 并且file3.cpp已经修改了内容(即,不仅仅是格式化)。
我想存储对这三个文件的更改,然后签出旧版本,以便之后我可以重新应用对这些文件的更改。

使用 Git 2.13(2017 年第二季度), git stash 将正式提供一种方法来存储特定文件的更改

git stash push [--] [<pathspec>...]

请参阅Thomas Gummerer ( ) 的提交9e14090、提交1ada502、提交df6bba0(2017 年 2 月 28 日)和提交 9ca6326提交 6f5ccd4提交 f5727e2(2017 年 2 月 19 日(由Junio C Hamano 合并——提交 44c3f09中,2017 年 3 月 10 日)tgummerer
gitster

正如现在记录的

为了快速制作快照,您可以省略“推送”。
在这种模式下,不允许使用非选项参数来防止拼写错误的子命令进行不需要的存储。
两个例外是stash -p充当别名stash push -p和路径规范,允许在双连字符后--消除歧义。

当 pathspec 被赋予 ' git stash push' 时,新的 stash 仅记录与 pathspec 匹配的文件的修改状态
然后索引条目和工作树文件也将回滚到 HEAD仅针对这些文件的状态,从而使与路径规范不匹配的文件保持不变。

请注意,正如medmunds评论中指出的那样,这将使用相对于 git repo 的根文件夹的git stash路径。


Git 2.26(2020 年第二季度)中,“ git rm”和“ git stash”学习了新的“ --pathspec-from-file”选项

如果您有要存储的文件列表filesToStash.txt,那么这就足够了:

git stash --pathspec-from-file=filesToStash.txt` is enough.
于 2017-03-22T22:10:39.470 回答
26

一个不错的选择是使用交互式存储模式。

git stash --patch

它的工作方式主要类似于交互式添加模式:您将看到一系列差异,显示您在工作树中所做的更改,您必须选择要存储的文件(或文件的某些部分!) ,其余的将保持不变。

来自man git-stash

使用 --patch,您可以交互地从 HEAD 和要隐藏的工作树之间的差异中选择块。存储条目的构造使其索引状态与存储库的索引状态相同,并且其工作树仅包含您以交互方式选择的更改。然后从您的工作树中回滚选定的更改。请参阅git-add(1) 的“交互模式”部分了解如何操作 --patch 模式。

在您的情况下,您将能够看到仅格式化的大块并单独存储它们,而不会丢失有意义的更改。

于 2016-04-14T08:27:49.743 回答
12

你也可以使用 git stash -p。通过这种方式,您可以选择应将哪些块添加到存储中,也可以选择整个文件。

系统会提示您针对每个大块执行一些操作:

y - stash this hunk
n - do not stash this hunk
q - quit; do not stash this hunk or any of the remaining ones
a - stash this hunk and all later hunks in the file
d - do not stash this hunk or any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help
于 2017-05-11T15:07:54.683 回答
4

这对IMO很有git diff用:git apply

git diff file2.cpp file2.h file3.cpp > ../my-changes.patch
git checkout ...
git apply ../my-changes.patch

之后diff,您可以检查补丁文件以确保您的所有更改都在那里。

请注意,您可能需要使用--reject应用选项,以防补丁无法完全应用。另请参阅apply 的手册页

于 2012-09-06T17:30:22.093 回答