我可以提供git-diff的补丁兼容输出吗?

197

我做了一些很简单的错误。我正在尝试准备一个普通的补丁文件,以便我可以重新应用一些更改:

$ git diff > before
$ git diff something_here > save.patch
$ git checkout . 
$ patch < save.patch
$ git diff > after
$ diff before after
$

使用something_here blank几乎可以工作,但文件名不正确。我认为我只是缺少一些选项。

在实际应用中,在检出后我会执行合并操作,所以修补程序可能会失败,但你知道我的意思。

编辑 我犯了一个错误,问错了问题。实际问题是,我想将我的更改保存起来,执行合并,然后重新应用更改,如果可能的话?我的提问方式有误,因为我习惯于使用补丁来解决这些问题,并且git diff看起来就像是它想让我这样做。

Charles Bailey的评论给出了正确的答案。对于我来说,git-apply是正确的选择(git-stash似乎比我需要的更加复杂,而rebase和bundles绝对超出了我的当前技能水平)。我将接受Charles给出的答案(因为您不能接受评论)。感谢所有的建议。

六年后的编辑 任何熟悉此主题的人都知道,我高估了git stash的难度。几乎每天我都会使用以下序列:

$ git stash
$ git merge
$ git stash pop

编辑,五年后我很大程度上放弃了使用git apply,而且几乎不再使用git stashgit rebase才是王道。


9
你特别想使用patch而不是git apply,是否有任何理由? - CB Bailey
3
即使那样,你真的需要补丁(patch)而不是像git stash或其他Git工具一样的东西吗? - CB Bailey
3
我认为git stash是您尝试的最简单的解决方案,但还有许多可行的方法。 - CB Bailey
5
有时候你需要向某人发送一个补丁,但又不想将整个 git 仓库一起发送,比如使用 git-svn 的情况。 - Elazar Leibovich
1
@CharlesBailey 在这里提醒一下,也许我只想应用一些更改,因此手动编辑补丁是一个快速的方法。 - Conrado
显示剩余3条评论
5个回答

259

只需使用-p1:无论如何,您都需要在--no-prefix情况下使用-p0,因此您可以省略--no-prefix并使用-p1

$ git diff > save.patch
$ patch -p1 < save.patch

$ git diff --no-prefix > save.patch
$ patch -p0 < save.patch

2
如果你想知道为什么,man文档已经很好地总结了 - 来源 - tutuDajuju
3
对于重命名操作,这种方法行不通;git diff输出的一行在patch中会被忽略。使用git apply是可行的方式。 - hraban

156

8
执行git diff --no-prefix master > diff.patch命令,然后执行git checkout masterpatch -p0 < diff.patch - Natim
3
@Natim 为了最终的安全起见,我建议在执行最后一个命令之前使用 patch --dry-run < diff.patch - ᴠɪɴᴄᴇɴᴛ
1
@ᴠɪɴᴄᴇɴᴛ,这样做有什么好处呢?既然我们正在使用 Git,我们不太可能失去任何东西,对吧? - Natim
2
@Natim,正如我所说,为了终极安全起见,在出现错误的情况下无需撤销任何操作。我还考虑到那些想在更一般的用例中使用patch(可能是使用由diff生成的补丁文件)的读者。 - ᴠɪɴᴄᴇɴᴛ
为了将 文件包含在你的补丁中,你需要同时在补丁中包括 "git diff --no-prefix --cached"。也许有更好的方法吗? - jamshid

16

在 git diffs 中,文件路径前面会多出一个路径段。你可以通过使用 patch 并指定 -p1 来删除该路径入口,如下所示:

patch -p1 < save.patch

12
  1. 我保存当前目录(包括未提交的文件)与当前HEAD之间的差异。
  2. 然后,您可以将save.patch文件传输到任何地方(包括二进制文件)。
  3. 在目标计算机上,使用git apply <file>应用补丁。

注意:它也会diff当前已暂存的文件。

$ git diff --binary --staged HEAD > save.patch
$ git reset --hard
$ <transport it>
$ git apply save.patch

哈哈哈,这很有趣。我几乎四年前就问过这个问题,而我一直在演变我的做法,但如果你昨天问我如何做到这一点,我会给你答案,并说我从这个问题的答案中得到了它。(实际上,我可能会使用裸的 git diff > save.patchgit checkout . 而不是重置,但是... - Michael Lorton
哦,没注意到这是4年前的 :P。顺便说一下,重置只是为了演示它的工作原理...我也没有看到有人使用git apply或使差异与您的状态相关并使指向最后提交的指针可用。仅执行git diff根本没有做任何事情。 - Matej
是啊,现在我想知道我是怎么发现 git apply 的。使用 git reset 时需要注意的是 git diff 的问题 - 仓库、索引和工作区之间的关系是个难点。 - Michael Lorton

8

一个有用的技巧,可以避免创建临时补丁文件:

git diff | patch -p1 -d [dst-dir]

1
正是我想要的。并且与存储完美配合! git stash show -p stash@{3} | patch -p1 -d [dst-dir] - dtmland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接