Git 选择性地从文件恢复本地更改

在我的 git 回购,这是跟踪一个 svn 回购,我做了一些编辑到一个单一的文件。

现在我想恢复这些更改(如 svn 恢复) ,但只恢复文件的部分内容。

我希望能够查看文件上的差异,丢弃(恢复)我不想要的变化,并保留我想要的变化。

git add -i

指挥部似乎有这样的选择,但我不想上演这一幕。

37470 次浏览

您可以对文件运行 git diff,保存生成的 diff,编辑它以删除 要保存的更改,然后通过 patch -R运行它以撤消其余的 diff。

git diff file.txt >patch.tmp
# edit patch.tmp to remove the hunks you want to keep
patch -R <patch.tmp

看来你想

 git revert --no-commit $REVSISON

然后你可以使用

 git diff --cached

看看在提交之前会做出什么改变(因为回复只是向前提交,复制了过去改变的相反方向)

如果你使用的是纯 Git 存储库,你可以根据你的目标,利用交互式 rebase (git rebase -i)回到你不喜欢的提交,并且回溯性地编辑提交,这样你不喜欢的改变就不会发生,但是这通常只有在你不想再看到它的时候才会发生。

您可以直接使用 git checkout -p来完成这项工作,请参阅下面的 Daniel Stutzbach 的回答


旧答案(在 checkout -p出现之前) :

你可以这样做:

git add -i

(选择你想要保留的大块头)

git commit -m "tmp"

现在您有了一个只包含您希望保留的更改的提交,其余的都是非暂存的。

git reset --hard HEAD

此时,未提交的更改已被丢弃,因此您拥有一个干净的工作目录,其中包含您希望保持提交的更改。

git reset --mixed HEAD^

这会删除最后一次提交(“ tmp”) ,但会保留工作目录中的修改,取消暂存。

编辑: 用 --mixed代替 --soft,以清理中转站区域。

重新阅读这个问题,听起来好像你想要恢复工作树中的更改,而不是之前提交的更改,但是其他一些答案听起来好像我的阅读可能是错误的。你能澄清一下吗?

如果更改只是在你的工作副本中,那么最简单的方法就是分阶段进行你想要保持的更改:

git add -i <file>

然后通过检查索引版本来丢弃那些你不想保留的更改:

git checkout -- <file>

然后,如果你不想让这些变化上演,那么取消它们:

git reset -- <file>

此配方仅将选定的更改还原到文件(或您指定的文件) ,并且不会创建任何需要还原的临时提交。

如果你只想有选择地应用前一次提交中所做的一些更改,那么你可以先将一个文件重置为前一次提交的状态:

git reset <commit_before_first_unwanted_change> -- <file>

然后,您可以按照以前的 git add -i <file>配方来处理那些您想要保留的更改,git checkout -- <file>抛弃不需要的更改,而 git reset -- <file>“取消处理”更改。

我相信你可以用最简单的方法:

git checkout -p <optional filename(s)>

页面上写着:

   −p, −−patch
Interactively select hunks in the difference between the <tree−ish>
(or the index, if unspecified) and the working tree. The chosen
hunks are then applied in reverse to the working tree (and if a
<tree−ish> was specified, the index).
       This means that you can use git checkout −p to selectively discard
edits from your current working tree.

当文件位于我通过 ssh 终端访问的服务器上时,这里的答案中描述的命令行选项非常方便。 但是,当文件在我的本地计算机上时,我更喜欢以下方式:

在 netbeans 编辑器中打开该文件(它附带了 git 支持)。Netbeans 将红色/绿色/蓝色标记放在行号处,分别表示删除/添加/修改的位置。

右键单击这些标记中的任何一个都可以选择撤消该更改。 此外,您可以右键单击红色和蓝色标记,找到在弹出窗口中看到旧版本。