你如何使用git format-patch将提交压缩成一个补丁?

ski*_*ppy 162 git patch squash git-squash

我在一个分支上有八个提交,我想通过电子邮件发送给一些不是git开悟的人.到目前为止,我所做的每件事都给了我8个补丁文件,或者从一开始就开始给分支历史上每次提交的补丁文件.我使用git rebase --interactive来压缩提交,但是现在我尝试的所有内容从一开始就给了我数以万计的补丁.我究竟做错了什么?

git format-patch master HEAD # yields zillions of patches, even though there's 
                             # only one commit since master
Run Code Online (Sandbox Code Playgroud)

Ada*_*der 181

我建议在一次性分支上执行此操作,如下所示.如果您的提交位于"newlines"分支中并且您已经切换回"master"分支,那么这应该可以解决问题:

[adam@mbp2600 example (master)]$ git checkout -b tmpsquash
Switched to a new branch "tmpsquash"

[adam@mbp2600 example (tmpsquash)]$ git merge --squash newlines
Updating 4d2de39..b6768b2
Fast forward
Squash commit -- not updating HEAD
 test.txt |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

[adam@mbp2600 example (tmpsquash)]$ git commit -a -m "My squashed commits"
[tmpsquash]: created 75b0a89: "My squashed commits"
 1 files changed, 2 insertions(+), 0 deletions(-)

[adam@mbp2600 example (tmpsquash)]$ git format-patch master
0001-My-squashed-commits.patch
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!

  • 对我来说,它更可靠的使用`git comit -m"我的压缩提交"`否则它会添加其他未跟踪的文件 (5认同)
  • 这是我想在本地保存历史记录时使用的(如果我需要编辑补丁).否则我只使用rebase -i并压缩提交. (2认同)

Tar*_*ast 130

只是为了添加一个解决方案:如果你使用它:

git format-patch master --stdout > my_new_patch.diff
Run Code Online (Sandbox Code Playgroud)

然后它仍然是8个补丁...但它们都将在一个补丁文件中并将作为一个应用:

git am < my_new_patch.diff
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个解决方案.值得注意的是,它可能会创建比@Adam Alexander描述的方法更大的补丁.这是因为某些文件可能会通过提交进行多次编辑.即使某个文件已还原,此方法也会单独处理每个提交.但大多数时候这不是问题. (13认同)

Rob*_*rco 20

我总是在你的例子中使用git diff,比如

git diff master > patch.txt
Run Code Online (Sandbox Code Playgroud)

  • 除了你丢失所有提交消息和元数据.git format-patch的美妙之处在于可以从一组补丁中重建整个分支. (14认同)
  • 不错的选择,但考虑到'git diff'不能包含二进制差异(也许有一个选项可以做到). (2认同)

Von*_*onC 18

如您所知,a git format-patch -8 HEAD将为您提供八个补丁.

如果您希望您的8个提交显示为一个,并且不介意重写您的分支(o-o-X-A-B-C-D-E-F-G-H)的历史记录,您可以:

git rebase -i
// squash A, B, C, D, E ,F, G into H
Run Code Online (Sandbox Code Playgroud)

或者,这将是一个更好的解决方案,重播所有8个提交X(在8次提交之前提交)在新分支上

git branch delivery X
git checkout delivery
git merge --squash master
git format-patch HEAD
Run Code Online (Sandbox Code Playgroud)

这样,您只在"交付"分支上有一个提交,它代表您最近的8次提交


rec*_*rec 18

这是亚当亚历山大答案的改编,以防你的变化在主分支.这样做如下:

  • 从我们想要的点创建一个新的一次性分支"tmpsquash"(查找运行"git --log"或使用gitg的SHA密钥.选择你想成为tmpsquash head的提交,在master之后的提交将是被压扁的提交).
  • 合并从master到tmpsquash的更改.
  • 将压扁的变化提交给tmpsquash.
  • 使用压缩提交创建补丁.
  • 回到主分公司

laura@rune:~/example (master)$ git branch tmpsquash ba3c498878054e25afc5e22e207d62eb40ff1f38
laura@rune:~/example (master)$ git checkout tmpsquash
Switched to branch 'tmpsquash'
laura@rune:~/example (tmpsquash)$ git merge --squash master
Updating ba3c498..40386b8
Fast-forward
Squash commit -- not updating HEAD

[snip, changed files]

11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example  (tmpsquash)$ git commit -a -m "My squashed commits"
[test2 6127e5c] My squashed commits
11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example  (tmpsquash)$ git format-patch master
0001-My-squashed-commits.patch
laura@rune:~/example  (tmpsquash)$ git checkout master
Switched to branch 'master'
laura@rune:~/example  (master)$
Run Code Online (Sandbox Code Playgroud)


woo*_*666 8

最简单的方法是使用git diff, 并添加git log如果您想要壁球方法将输出的组合提交消息。例如,要在 commitabcd和之间创建补丁1234

git diff abcd..1234 > patch.diff
git log abcd..1234 > patchmsg.txt
Run Code Online (Sandbox Code Playgroud)

然后在应用补丁时:

git apply patch.diff
git add -A
git reset patch.diff patchmsg.txt
git commit -F patchmsg.txt
Run Code Online (Sandbox Code Playgroud)

不要忘记处理非文本文件时的--binary论点git diff,例如图像或视频。


kas*_*ndr 7

两个标签之间的格式补丁:

git checkout <source-tag>
git checkout -b <tmpsquash>
git merge --squash <target-tag>
git commit -a -m "<message>"
git format-patch <source-tag>
Run Code Online (Sandbox Code Playgroud)