从当前工作目录中未提交的更改创建一个 git 补丁
Posted
技术标签:
【中文标题】从当前工作目录中未提交的更改创建一个 git 补丁【英文标题】:Create a git patch from the uncommitted changes in the current working directory 【发布时间】:2011-07-06 18:17:31 【问题描述】:假设我的工作目录中有未提交的更改。如何在不创建提交的情况下从这些补丁中制作补丁?
【问题讨论】:
接受的答案可能应该更改,因为第二个答案的受欢迎程度几乎是四倍。 @TimOgilvy 同意了。 OP应该这样做。第二个答案更受欢迎,并提供更多信息 我认为值得一提的是,您也需要对标题中未提交的更改进行补丁。 【参考方案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 diff
用于未暂存的更改。
git diff --cached
用于分阶段更改。
git diff HEAD
用于分阶段和非分阶段的更改。
【讨论】:
是的,git diff 是 git apply 的倒数git format-patch
还包括二进制差异和一些元信息。实际上,这将是创建补丁的最佳选择,但 afaik 这仅适用于签入源/更改,对吧?
有时创建一个相对于当前目录的补丁可能很有用。为此,请使用git diff --relative
git diff > a.patch 将其写入文件
简洁近乎讽刺,下面的答案更有帮助。【参考方案3】:
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 中创建相同补丁的方法(我不建议使用该工具):
-
提交您的工作更改
右击分支根目录,点击
Tortoise Git
-> Create Patch Serial
-
选择合适的范围(
Since
: FETCH_HEAD
将在您同步良好的情况下工作)
创建补丁
Tortise Git
-> Show Log
在你的临时提交之前右击提交,然后点击reset "<branch>" to this...
选择Mixed
选项
以及如何应用它们:
-
右击分支根目录,点击
Tortoise Git
-> Apply Patch Serial
选择正确的补丁并应用它们
右击分支根目录,点击Tortise Git
-> Show Log
在补丁提交之前右击提交,然后点击reset "<branch>" to this...
选择Mixed
选项
【讨论】:
从技术上讲,这确实需要创建一个 OP 要求避免的提交,但这是一个临时的,无论如何答案都是有用的。【参考方案4】:要使用修改过的文件和新文件(分阶段)创建补丁,您可以运行:
git diff HEAD > file_name.patch
【讨论】:
谢谢,就我而言,这个答案有效,但git diff --cached > mypatch.patch
无效。
我有一个问题:file_name.patch
可以被patch
命令使用吗?它们相互兼容吗?
git diff + git diff --cached/staged == git diff HEAD(显示自上次提交以来的所有更改)
@RakshithRavi afaik,是的。您可以使用git diff HEAD > file-name.patch
创建的补丁,例如如下:patch --forward --strip=1 < file-name.patch
【参考方案5】:
我喜欢:
git format-patch HEAD~<N>
其中<N>
是保存为补丁的最后提交数。
该命令的详细使用方法在DOC
UPDHere你可以找到如何应用它们。
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中没有指定,它们都是相关且正确的,所以选择添加它。显式优于隐式!
【讨论】:
以上是关于从当前工作目录中未提交的更改创建一个 git 补丁的主要内容,如果未能解决你的问题,请参考以下文章