【问题标题】:Can I get a patch-compatible output from git-diff?我可以从 git-diff 获得补丁兼容的输出吗?
【发布时间】:2011-01-06 00:39:03
【问题描述】:

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

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

something_hereblank 几乎可以工作,但文件名不正确。我想我只是缺少一些选择。

在现实生活中,我将在结帐后进行合并,因此补丁可能会在那里失败,但你明白我的意思。

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

Charles Bailey 的 评论 给出了正确答案。对我来说, git-apply 是正确的做法(git-stash 看起来比我需要的更重,并且 rebase 和 bundles 绝对超出了我目前的技能水平。)我将接受 Charles 给出的答案(因为你不能接受评论)。谢谢大家的建议。

编辑,6 年后 熟悉这个主题的人都知道,我高估了git stash 的难度。几乎每天左右,我都会使用以下顺序:

$ git stash
$ git merge
$ git stash pop

【问题讨论】:

  • 您有什么理由特别想使用patch 而不是git apply 吗?
  • 即便如此,你真的需要补丁而不是像 git stash 或其他 git 工具这样的东西吗?
  • 后期编辑,我认为git stash 是您尝试做的最简单的解决方案,但有很多方法可行。
  • @Malvolio:确实如此,您甚至不必想一个临时文件名来存储您的补丁。
  • @Charlse,有时您需要将补丁发送给没有整个 git 存储库的人。例如,如果使用 git-svn.

标签: git


【解决方案1】:

只需使用-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

【讨论】:

  • 如果您想知道为什么,the man docs 总结得很好 - source
  • 这不适用于重命名; git diff 输出一行 patch 忽略。 git apply 是要走的路。
【解决方案2】:

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

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

但通常情况下,直接使用git diff 然后使用输出提供给git apply 会更容易。

大多数时候我尽量避免使用文本补丁。通常一个或多个临时提交与 rebase、git stash 和 bundle 结合起来更容易管理。

对于您的用例,我认为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

【讨论】:

  • git diff --no-prefix master &gt; diff.patch 然后git checkout master patch -p0 &lt; diff.patch
  • @Natim 为了安全起见,我建议在发出最后一个命令之前使用patch --dry-run &lt; diff.patch
  • @ᴠɪɴᴄᴇɴᴛ 这样做有什么好处?由于我们使用的是 git,所以我们不太可能丢失任何东西,不是吗?
  • @Natim 正如我所说,只是为了最终安全,如果出现错误,无需撤消任何操作。我也在考虑阅读这篇文章并希望在更一般的用例中在 git 之外使用 patch(可能使用由 diff 生成的补丁文件)的人。
  • 为了在您的补丁中包含 new 文件,您需要在修补。也许有更好的方法?
【解决方案3】:

git diff 在文件路径前有一个额外的路径段。您可以通过指定带有补丁的 -p1 来去除路径中的 this 条目,如下所示:

patch -p1 < save.patch

【讨论】:

    【解决方案4】:
    1. 我保存当前目录(包括未提交的文件)与当前 HEAD 的差异。
    2. 然后您可以将save.patch 文件传输到任何地方(包括二进制文件)。
    3. 在您的目标机器上,使用git apply &lt;file&gt; 应用补丁

    注意:它也是当前暂存文件的差异。

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

    【讨论】:

    • 哈哈哈。那很好笑。大约四年前我问过这个问题,我一直这样做的方式已经发生了变化,但如果你昨天问我怎么做,我会给出你的答案并说我是从这个问题的答案中得到的。 (实际上我可能会使用裸 git diff &gt; save.patchgit checkout . 而不是重置,但是是的......
    • 哦,没注意到它已经 4 岁了:P。顺便说一句,重置只是为了证明它有效。我也没有看到任何人使用git apply 或使差异与您的状态相关以及指向最后一次提交的指针可用。只做git diff 什么都没做
    • 是的,现在我想知道我是怎么知道git apply的。 git diff 的问题(我认为)来自使用 git reset - 回购、索引和工作区域之间的关系是问题。
    【解决方案5】:

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

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

    【讨论】:

    • 正是我想要的。也可以与 stash 完美搭配! git stash show -p stash@{3} | patch -p1 -d [dst-dir]
    猜你喜欢
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-13
    • 2023-03-09
    • 2022-09-29
    • 2013-01-01
    • 1970-01-01
    相关资源
    最近更新 更多