【问题标题】:Create a git patch from the uncommitted changes in the current working directory从当前工作目录中未提交的更改创建一个 git 补丁
【发布时间】:2011-07-06 18:17:31
【问题描述】:

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

【问题讨论】:

  • 接受的答案可能应该更改,因为第二个答案的受欢迎程度几乎是四倍。
  • @TimOgilvy 同意了。 OP应该这样做。第二个答案更受欢迎,并提供更多信息
  • 我认为值得一提的是,您也需要对标题中未提交的更改进行补丁。

标签: git git-patch


【解决方案1】:

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

git diff > mypatch.patch

但有时您正在做的部分事情是未跟踪的新文件,不会出现在您的git diff 输出中。所以,打补丁的一种方法是为新的提交(git add 每个文件,或只是git add .)暂存所有内容,但不进行提交,然后:

git diff --cached > mypatch.patch

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

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

您可以稍后应用补丁:

git apply mypatch.patch

【讨论】:

  • 我正是这样做的,并在执行 git apply 时得到“致命:无法识别的输入”。知道是什么原因造成的以及如何解决吗?
  • @Vitaly:如果您使用文本编辑器打开补丁,您的补丁是否可读?它应该是干净的,没有奇怪的字符,例如,如果设置了 color.diff 设置,您的补丁将有一些“颜色字符”,可以使“git apply”失败,在这种情况下尝试git diff --no-color。否则,它看起来像一个编码问题。
  • 要从已经暂存的更改中创建补丁,您也可以使用git diff --staged > mypatch.patch,因为--staged--cached 的同义词。我认为它更容易记住。
  • 与“未跟踪的新文件”相关:“git diff”和“git diff --cached”仅在首先调用“git add ”时才有效。 (我是 git 新手,想知道为什么我每次都得到一个空补丁)
  • 这很容易让我摆脱了奇怪的合并/变基地狱,谢谢:)
【解决方案2】:

git diff 用于未暂存的更改。

git diff --cached 用于分阶段更改。

git diff HEAD 用于分阶段和非分阶段的更改。

【讨论】:

  • 是的,git diff 是 git apply 的倒数
  • git format-patch 还包括二进制差异和一些元信息。实际上,这将是创建补丁的最佳选择,但 afaik 这仅适用于签入源/更改,对吧?
  • 有时创建一个相对于当前目录的补丁可能很有用。为此,请使用git diff --relative
  • git diff > a.patch 将其写入文件
  • 简洁近乎讽刺,下面的答案更有帮助。
【解决方案3】:

git diffgit apply 适用于文本文件,但不适用于二进制文件。

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

git format-patch <options...>

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

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

这将回滚您的临时提交。最终结果使您的工作副本(故意)变脏,并带有您最初所做的相同更改。

在接收端,您可以使用相同的技巧将更改应用到工作副本,而无需提交历史记录。只需应用补丁和git reset --mixed &lt;SHA of commit *before* the patches&gt;

请注意,您可能必须进行良好的同步才能使整个选项正常工作。我在应用补丁时看到了一些错误,因为制作补丁的人没有像我一样拉下尽可能多的更改。可能有办法让它工作,但我还没有深入研究。


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

  1. 提交您的工作更改
  2. 右击分支根目录,点击Tortoise Git -> Create Patch Serial
    1. 选择合适的范围(Since: FETCH_HEAD 将在您同步良好的情况下工作)
    2. 创建补丁
  3. 右击分支根目录,点击Tortise Git -> Show Log
  4. 在你的临时提交之前右击提交,然后点击reset "&lt;branch&gt;" to this...
  5. 选择Mixed 选项

以及如何应用它们:

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

【讨论】:

  • 从技术上讲,这确实需要创建一个 OP 要求避免的提交,但这是一个临时的,无论如何答案都是有用的。
【解决方案4】:

要使用修改过的文件和新文件(分阶段)创建补丁,您可以运行:

git diff HEAD > file_name.patch

【讨论】:

  • 谢谢,就我而言,这个答案有效,但git diff --cached &gt; mypatch.patch 无效。
  • 我有一个问题:file_name.patch 可以被patch 命令使用吗?它们相互兼容吗?
  • git diff + git diff --cached/staged == git diff HEAD(显示自上次提交以来的所有更改)
  • @RakshithRavi afaik,是的。您可以使用git diff HEAD &gt; file-name.patch 创建的补丁,例如如下:patch --forward --strip=1 &lt; file-name.patch
【解决方案5】:

我喜欢:

git format-patch HEAD~<N>

其中&lt;N&gt; 是保存为补丁的最后提交数。

该命令的详细使用方法在DOC

UPD
Here你可以找到如何应用它们。

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 .

【讨论】:

  • 有一种比创建提交和取消提交更简单的方法。 git diff --cached --binary
  • @IgorGanapolsky:你注意到别名了吗? git config --global alias.make-patch ....
  • 基于它会产生像../folder这样的路径,它不仅仅在当前工作目录中这样做。
【解决方案6】:

如果您想执行二进制,请在运行 git diff 时提供 --binary 选项。

【讨论】:

    【解决方案7】:

    我们也可以指定文件,只包含有相对变化的文件,尤其是当它们跨越多个目录时,例如

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

    我发现这在答案或cmets中没有指定,它们都是相关且正确的,所以选择添加它。显式优于隐式!

    【讨论】:

      猜你喜欢
      • 2014-11-28
      • 2012-09-05
      • 1970-01-01
      • 2012-03-12
      • 1970-01-01
      • 2013-02-08
      • 2011-08-17
      • 1970-01-01
      • 2023-03-03
      相关资源
      最近更新 更多