我可以从git-diff获得补丁兼容的输出吗?


160

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

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

使用something_here 空白几乎可以使用,但是文件名不正确。我想我只是缺少一些选择。

在现实生活中,我将在结帐后进行合并,因此补丁可能会在此处失败,但是您会发现我的意思。

在这里编辑我的错误,询问错误的问题。实际的问题是,如果可能的话,我想保存所做的更改,进行合并,然后重新应用更改?我问错了方法,因为我习惯于使用补丁来解决这类问题,而git diff这正是它想要我做的。

查尔斯·贝利(Charles Bailey)的评论给出了正确的答案。对我来说,执行git-apply是正确的事情(git-stash看起来比我需要的还要重,并且重新绑定和捆绑绝对超出了我的当前技能水平。)我将接受Charles给出的答案(因为您无法接受评论)。感谢所有的建议。

编辑,六年后 正如熟悉该主题的任何人都知道的那样,我高估了的难度git stash。几乎每天左右,我将使用以下顺序:

$ git stash
$ git merge
$ git stash pop

8
您是否有特定原因要使用patch而不是git apply
CB Bailey

3
即使那样,您是否真的需要修补程序而不是类似git stash或其他git工具的补丁程序?
CB Bailey

3
编辑后,我认为这git stash是您尝试做的最简单的解决方案,但是有很多方法可以起作用。
CB Bailey

1
@Malvolio:确实是这样,你甚至不用去思考一个临时文件名的你的补丁存储英寸
CB贝利

4
@Charlse,有时您需要将补丁发送给没有整个git仓库的人。例如,如果使用git-svn
Elazar Leibovich

Answers:


139

如果要使用补丁,则需要删除a/ b/git默认使用的前缀。您可以使用--no-prefix选项来执行此操作(也可以使用patch的-p选项来执行此操作):

git diff --no-prefix [<other git-diff arguments>]

不过,通常情况下,更简单的用法是直接使用git diff,然后使用输出来馈送给git apply

大多数时候,我会尽量避免使用文本补丁。通常是将临时提交中的一项或多项与变基一起进行,git stash并且捆绑包更易于管理。

对于您的用例,我认为这stash是最合适的。

# save uncommitted changes
git stash

# do a merge or some other operation
git merge some-branch

# re-apply changes, removing stash if successful
# (you may be asked to resolve conflicts).
git stash pop

7
git diff --no-prefix master > diff.patch然后git checkout master patch -p0 < diff.patch
Natim 2014年

1
@Natim为了最终安全,我建议patch --dry-run < diff.patch在发出最后一条命令之前使用。
ᴠɪɴᴄᴇɴᴛ

1
@ᴠɪɴᴄᴇɴᴛ这样做的好处是什么?由于我们正在使用git,因此不太可能丢失任何东西,不是吗?
纳蒂姆'16

1
@Natim正如我所说,仅出于最终安全考虑,如果出现错误,无需撤消任何操作。我也正在考虑阅读此书的人,并希望在更一般的用例中在patchgit之外使用(也许使用生成的补丁文件diff)。
ᴠɪɴᴄᴇɴᴛ

为了包括在你的补丁文件,你需要包括“git的差异--no前缀--cached”的补丁。也许有更好的方法?
jamshid

219

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

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

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

1
如果你想知道为什么,男人文档概括起来很好-
tutuDajuju

3
这不适用于重命名;git diff输出patch忽略的行。git apply是要走的路。
hraban

17

git diffs在文件路径之前有一个额外的路径段。您可以通过使用patch指定-p1来删除路径中的此项,如下所示:

patch -p1 < save.patch

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

注意:它也与当前暂存的文件不同。

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

哈哈哈 那很好笑。我差不多是四年前问这个问题的,而我一直在做的事情已经演变了,但是如果您昨天问我如何做,我会给出您的回答,并说我从这个问题的回答中得到了答案。(实际上,我可能会使用裸机git diff > save.patchgit checkout .不是重置,但是是的……
Malvolio 2014年

哦,没有注意到它的4年历史:P。顺便说一句,重设只是为了演示它的工作。我也看不到有人使用git apply或使diff与您的状态以及指向最后可用提交的指针相关。做git diff一切都没做
Matej 2014年

是的,现在我想知道如何找到有关git apply。问题git diff(我认为)来自于使用git reset-回购,索引和工作区域之间的关系是问题。
马尔沃里奥2014年

8

避免创建临时补丁文件的有用技巧:

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

正是我想要的。还可以完美地与藏匿地一起使用!git stash show -p stash@{3} | patch -p1 -d [dst-dir]
dtmland
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.