git subtree push --squash不会压缩提交

10

我正在使用git subtree来组织我的git代码库。假设我有一个名为repo的主要代码库和一个名为lib的库。

我成功地通过压缩其历史记录来“导入”lib代码库。现在,我想通过压缩历史记录来向lib贡献代码。但这似乎行不通:我尝试将--squash选项指定为git subtree push,但查看历史记录时,我仍然发送了所有提交记录。

如何复现问题

这里是一个脚本,展示了复现该问题所需的最小命令:

#!/bin/bash
rm -rf lib lib-work repo

# repo is the main repository
git init repo
# lib is the 'subtreed' repository (bare to accept pushes)
git init --bare lib

git clone lib lib-work
cd lib-work
# adding a bunch of commits to lib
echo "v1" > README
git add README
git commit -m 'lib commit 1'
echo "v2" > README
git add README
git commit -m 'lib commit 2'
echo "v3" > README
git add README
git commit -m 'lib commit 3'
git push origin master
cd ..

cd repo
# adding initial commit to have a valid HEAD
echo "v1" > README
git add README
git commit -m 'repo commit 1'
git remote add lib ../lib
git subtree add --prefix lib lib master --squash
echo "v4" > lib/README
git add lib/README
git commit -m 'repo commit 2'
echo "v5" > lib/README
git add lib/README
git commit -m 'repo commit 3'
echo "v6" > lib/README
git add lib/README
git commit -m 'repo commit 4'
#git log --all --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s%Creset' --abbrev-commit
# "not working" command :
git subtree push --prefix lib lib master --squash

# pretty print the history
git log --all --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s%Creset' --abbrev-commit
cd ../lib
echo
git log --all --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s%Creset' --abbrev-commit

git log 显示问题

两个 git log blabla 命令的输出结果如下:

* b075d5e - (HEAD, master) repo commit 4
* ebdc7c7 - repo commit 3
* 9f1edab - repo commit 2
*   3d48bca - Merge commit '34e16a547819da7e228f3add35efe86197d2ddcb' as 'lib'
|\
| * 34e16a5 - Squashed 'lib/' content from commit 2643625
* 3f1490c - repo commit 1
* 1f86fe3 - (lib/master) repo commit 4
* 9f1639a - repo commit 3
* 8bd01bd - repo commit 2
* 2643625 - lib commit 3
* 3d64b8c - lib commit 2
* aba9fcb - lib commit 1

并且:

* 1f86fe3 - (HEAD, master) repo commit 4
* 9f1639a - repo commit 3
* 8bd01bd - repo commit 2
* 2643625 - lib commit 3
* 3d64b8c - lib commit 2
* aba9fcb - lib commit 1

正如您所见,虽然我指定了squash选项,但lib仍看到了“repo commit 2,3,4”。相反的方式起作用,因此出现了 “Squashed 'lib/' content from commit f28bf8e'”。

我尝试了在Windows上使用git版本1.8.1.msysgit.1,在Linux上使用git版本1.8.3.4。

那么为什么--squash选项不会压缩呢?

附带问题

为什么lib/master出现在repo存储库的日志中? 仅当“失败”的git push之后才会出现。如果取消注释第一个git log blabla,则会得到以下输出,显示已存档的历史记录,但没有lib/master的迹象:

* b075d5e - (HEAD, master) repo commit 4
* ebdc7c7 - repo commit 3
* 9f1edab - repo commit 2
*   3d48bca - Merge commit '34e16a547819da7e228f3add35efe86197d2ddcb' as 'lib'
|\
| * 34e16a5 - Squashed 'lib/' content from commit 2643625
* 3f1490c - repo commit 1

对于这个附加问题,你看到额外的日志是因为使用了 --all 选项。使用该选项就像获取 refs/ 中所有引用的日志一样,因为推送操作在那里创建了一个新的引用,因此它会与 HEAD 的日志一起打印出来。 - Maic López Sáenz
我认为你在附加问题中的日志是错误的,或者可能是你创建存储库的不同时间,因为哈希值与你上面提供的不匹配。 - Maic López Sáenz
@LopSae,谢谢 :) 有没有办法防止推送添加新引用?如果没有,为什么获取不需要添加引用?关于副问题,抱歉造成困惑,我确实后来进行了测试,这就是为什么提交不同的原因。我更新了问题。 - ibizaman
1
通过使用 git subtree push 命令,您执行的是一次分割操作(split),它会创建一个分支(即额外的引用),然后再将该引用推送到服务器上。当您只使用 split 命令时,它将只创建一个提交记录而不创建新的分支,split 命令将只打印出所创建的提交记录哈希值。 - Maic López Sáenz
我理解,对于 push 命令的新分支创建并不在意,但是我不想看到它。看起来用 --branches 替换 --all 就可以解决问题,日志手册链接 - ibizaman
显示剩余2条评论
3个回答

9

可能这是subtree命令文档中的一个错误。

Git的手册中指出:

options for 'add', 'merge', 'pull' and 'push'
    --squash              merge subtree changes as a single commit

如果您查看原始子树项目中的更详细文档,您会注意到--squash选项仅在addmerge中进行了解释,因为该功能是为将内容引入您的代码库的过程而描述的。由于pull是合并的修改形式,因此也暗示它可以使用--squash
手册中列出的push没有意义。 git subtree push子命令是git subtree splitgit push的组合。这意味着--squash也应该是split支持的选项,但是手册列表中没有列出split。文档中也从未说明过它可以使用--squash--squash选项确实被splitpush接受,但是经过实验后发现它没有任何区别,就像您的例子所述一样。我认为这只是一个错误,被splitpush命令忽略了。

似乎就是这样:当在subtree文件中深入挖掘时,您可以看到squash选项在cmd_add_commit()cmd_merge()中使用,但不在cmd_split()中使用。 - ibizaman
2
更新:我已经向git邮件列表发送了一个修补程序,希望很快能收到他们的回复 :) - ibizaman

6

现在(Git 2.5,2015年第二季度)已在官方git subtree文档中确认。

请参见提交6ccc71aDanny Lin (danny0838), 2015年5月7日。
(由Junio C Hamano -- gitster --合并在提交6263f58, 2015年5月22日)

contrib/subtree: 没有push --squash

文档说--squash用于'add', 'merge', 'pull'和'push', 但实际上--squash不会改变'push'的行为。
请更正文档。

--squash:

这个选项仅适用于addmergepull命令。

随着 Git 2.29 (2020年第四季度) 的推出,子树文档(位于 contrib/ 目录下)更加清晰。

请参见 提交记录 ce820cb提交记录 f99c0c9(由 Danny Lin (danny0838) 于 2020年8月18日提交)。
(由 Junio C Hamano -- gitster -- 在 2020年8月24日合并,提交记录为 8923a45

contrib/subtree: 文档中的 'push' 不支持 '--squash' 参数

签名:Danny Lin

git subtree push 不支持 --squash,如先前在 6ccc71a9 中所示 ("contrib/subtree: there's no push --squash", 2015-05-07, Git v2.5.0-rc0 -- merge listed in batch #4)

文档 不再提到 push


0
我发现这个线程,因为我刚遇到了一个问题,即子树推送发送了父仓库整个历史记录的所有提交,而不仅仅是与新添加的子树相关的提交。结果发现,由于之前的子树添加操作失败,子树缓存出现了某种损坏。我不得不删除.git\subtree-cache目录来解决这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接