根据当前工作目录中的更改创建一个git补丁


878

假设我在工作目录中未提交更改。如何在不创建提交的情况下从这些文件制作补丁?


29
鉴于第二个答案的受欢迎程度几乎是后者的四倍,因此应该更改接受的答案。
蒂姆·奥美

5
@TimOgilvy同意。OP应该这样做。第二个答案更受欢迎,并且提供了更多信息
John Demetriou

1
我认为值得一提的是,您还需要从标题中未提交的更改中获取补丁。
2i3r

Answers:


401

git diff进行无阶段的更改。 git diff --cached进行分阶段的更改。


12
是的,git diff是git apply的反函数
Spike Gronim 2011年

33
git format-patch还包括二进制差异和一些元信息。实际上,这是创建补丁的最佳选择,但是afaik这仅适用于签入源/更改,对吗?
埃里克

20
有时创建相对于当前目录的补丁可能有用。为此,请使用git diff --relative
ejboy 2013年

30
git diff> a.patch将其写入文件
qasimzee

139
简洁的讽刺意味深长,下面的答案更为有用。
航空

1863

如果您尚未提交更改,则:

git diff > mypatch.patch

但是有时候,您正在做的事情的一部分是新文件,这些新文件未跟踪且不会出现在git diff输出中。因此,做补丁的一种方法是将所有内容暂存为一个新的提交(git add每个文件或仅一个git add .),但不执行该提交,然后:

git diff --cached > mypatch.patch

如果要将二进制文件(例如mp3文件)添加到补丁中,请添加“ binary”选项:

git diff --cached --binary > mypatch.patch

您以后可以应用补丁:

git apply mypatch.patch

注意:您也可以将--staged用作的同义词--cached


127
非常感谢您提供的示例。与已接受的答案相反,您将向命令显示如何操作,而不仅仅是讲话。对我非常有帮助,并且为我完美无瑕:)
nuala 2013年

4
我正是这样做的,在执行git apply时得到了“致命的:无法识别的输入”。任何想法会导致此问题以及如何解决?
Vitaly 2013年

6
@Vitaly:如果使用文本编辑器打开修补程序,它是否可读?它应该干净整洁,没有奇怪的字符,例如,如果设置了color.diff设置,则您的补丁程序将包含一些“颜色字符”,这些颜色可能会使“ git apply”失败,在这种情况下,请尝试git diff --no-color。否则,它看起来像是编码问题。
jcarballo

3
与“未跟踪的新文件”相关:“ git diff”和“ git diff --cached”仅在首先调用“ git add <file>”时起作用。(我是git的新手,想知道为什么每次都会得到一个空补丁)
匿名

5
这很容易使我脱离一个奇怪的合并/重新设置地狱,谢谢:)
约翰·亨特

86

git diff并且git apply适用于文本文件,但不适用于二进制文件。

您可以轻松创建完整的二进制补丁,但必须创建一个临时提交。临时提交后,可以使用以下方法创建补丁:

git format-patch <options...>

制作补丁后,运行以下命令:

git reset --mixed <SHA of commit *before* your working-changes commit(s)>

这将回滚您的临时提交。最终结果使您的工作副本(有意地)与最初所做的更改一样脏了。

在接收方,您可以使用相同的技巧将更改应用于工作副本,而无需提交历史记录。只需应用补丁,然后git reset --mixed <SHA of commit *before* the patches>

请注意,您可能必须很好地同步才能使整个选项正常工作。当制作补丁的人没有像我所做的那样多的更改时,我看到了一些错误。可能有多种方法可以使其正常工作,但我并没有对其进行深入研究。


以下是在Tortoise Git中创建相同补丁的方法(不建议您使用该工具):

  1. 提交工作变更
  2. 右键单击分支的根目录,然后单击Tortoise Git->Create Patch Serial
    1. 可以任意选择范围是有道理的(SinceFETCH_HEAD如果你是良好的同步将工作)
    2. 创建补丁
  3. 右键单击分支的根目录,然后单击Tortise Git->Show Log
  4. 临时提交之前右键单击提交,然后单击reset "<branch>" to this...
  5. 选择Mixed选项

以及如何应用它们:

  1. 右键单击分支的根目录,然后单击Tortoise Git->Apply Patch Serial
  2. 选择正确的补丁并应用它们
  3. 右键单击分支的根目录,然后单击Tortise Git->Show Log
  4. 右键单击补丁提交之前的提交,然后单击reset "<branch>" to this...
  5. 选择Mixed选项

5
从技术上讲,这确实需要创建一次OP要求避免的提交,但这是临时的,无论如何答案都是有用的。
davenpcj

33

要同时创建已修改的文件和新文件的补丁,可以运行:

git diff HEAD > file_name.patch

谢谢,就我而言,此答案有效,但git diff --cached > mypatch.patch无效。
2016年

我有一个问题:命令file_name.patch可以使用patch吗?它们彼此兼容吗?
Rakshith Ravi

git的差异+ git的差异--cached /上演== git的差异HEAD(显示所有的变化,因为上次提交)
K.符号

20

我喜欢:

git format-patch HEAD~<N>

哪里<N>是保存为补丁的最后提交次数。

有关如何使用该命令的详细信息,请参见DOC。

UPD
在这里,您可以找到如何应用它们。

UPD对于那些不了解format-patch
添加别名的人:

git config --global alias.make-patch '!bash -c "cd ${GIT_PREFIX};git add .;git commit -m ''uncommited''; git format-patch HEAD~1; git reset HEAD~1"'

然后在项目存储库的任何目录下运行:

git make-patch

该命令将0001-uncommited.patch在您当前的目录中创建。修补程序将包含所有更改和未跟踪的文件,这些内容和下一条命令可见:

git status .

@jcarballo:我已经更新了答案。随时将您的任何留言通知我。
Eugen Konkov,

2
有比创建提交和取消提交更简单的方法。git diff --cached --binary
Gaurav Agarwal

9

如果要执行二进制操作,请--binary在运行时提供一个选项git diff


0

我们还可以指定文件,以仅包括具有相对更改的文件,尤其是当它们跨越多个目录时,例如

git diff ~/path1/file1.ext ~/path2/file2.ext...fileN.ext > ~/whatever_path/whatever_name.patch

我发现答案或注释中没有指定相关内容,而这些答案都相关且正确,因此选择添加它。显式胜于隐式!

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.