希望压缩提交,以便面向公众的项目没有无意义的提交消息,例如" temp"或" temp123"。
我正在寻找一种方法来使用git reset --soft HEAD~5
,但我不想随机选择数字5,而是想回到Git日志并找到所有与模式不匹配的提交,并且我点击了停止的模式。所以,让我们说git log
提交消息如下:
temp123
fooGit
temp
fml
temp24
tmp69
tttoday
publish/release:xyz
所以我会压制前7个最近的提交,但是留下所有内容"低于" publish/release:xyz
。
由于相当复杂的原因,从面向公众的分支机构发出的git merge --squash
对我来说不起作用,因为我最终在私有分支机构的项目中删除或重命名文件,所以有合并冲突太多了。在尝试了几种方法之后,我觉得最好用-f推向面向公众的分支,而不用担心这种冲突。
我认为在我的情况下更好的方法是像这样压缩提交:
# on private "dev" branch
# make a bunch of changes, rename files, yadda yadda
git add . && git add -A && git commit -am "temp" &&
git checkout -b squash_branch # we do squashing on this branch to be safer
git reset --soft head~15 # apparently this undoes commits for the last 15 commits
git commit -am "A serious commit message"
git push -u public master -f # overwrite public master
通过这种方式,我永远不必解决面向公众的分支和私有开发分支之间的冲突,这可能是超级无意义的,并且从我的经验中感到烦恼。
然而,我试图解决的问题与上面的数字15有关。我只是猜测有多少提交到#34;壁球"。我宁愿知道压扁的确切数字。
也许我可以对所有没有符合某种模式的Git提交消息的提交进行压缩?因此,当我运行壁球时,我创建一个具有特定模式的提交消息,让我们说它" XYZ"。我可以运行git reset --soft HEAD~(some git commit pattern matching to find the count)
吗?
还有一个问题。在git reset --soft
上进行压缩(squash_branch
)之后,我应该将该分支合并回私有dev
分支吗?
答案 0 :(得分:2)
你可以找到计数,但这有点危险,因为如果链中存在合并提交,它将是错误的数字(此处未说明):
git rev-list --count HEAD^{/publish/release:xyz}..HEAD
符号rev^{/text}
表示"从给定的rev
开始,搜索给定文本&的每个提交消息(la git log --grep
) #34 ;.因此,第一个表达式在其提交消息中与提交publish/release:xyz
匹配。然后,..
语法使用该提交的ID来删除提交和早先从名称HEAD
选择的提交集中提交。然后--count
给出了剩余提交的计数。因此,如果您的图表如下所示:
...--o--*--o--o--o--o <-- HEAD
其中*
是其中包含文本的提交,这会丢弃提交*
以及其他进一步提交,留下最后的四个o
提交HEAD
指向的节点。 --count
然后计算这四个提交并打印4
。
总的来说,这是一个糟糕的策略。通过使用分支或标记名称标记点来开始更好。分支或标记名称通过指向它来标识提交。而不是试图通过模式找到提交*
,只需在制作它时标记它:
git tag xyz
现在你有了这个:
tag:xyz
|
v
...--o--*--o--o--o <-- HEAD -> dev
和xyz..HEAD
为您提供正确的提交,您可以git reset --soft xyz
使分支标签dev
指回提交*
:
tag:xyz
|
v
...--o--* <-- HEAD -> dev
\
o--o--o [only findable via reflogs]
完成此操作后,只需删除标记。
(同样,您可以使用分支或标记名称;使用您喜欢的名称;我用标签说明了这一点,因为标签名称不是假设要移动,分支名称执行移动。实际上,只要您git checkout
分支然后进行提交或使用git reset
,它们就会自动 。标记名称指向一个特定的提交,并留在那里。)
请注意,您可以在创建标记时使用搜索表示法:
git tag xyz HEAD^{/publish/release:xyz}
也就是说,在创建标记名称时,您可以识别哪些提交标记。 (实际上对于分支名称也是如此。)然后,您可以使用git log --decorate
查看此标记,而gitk
等图形查看器通常会显示哪些提交也包含哪些标记。
(搜索和标记是更好地过渡到这一点的好方法,至少在理论上是习惯。)
答案 1 :(得分:1)
在您开始工作之前,我假设您的dev
分支跟踪master
。如果没有,请在进行任何临时提交之前创建一个新分支。
要确定从master
分支的点(以及重置为的点),请执行以下操作:
git merge-base master HEAD
您可以显示该点与HEAD
之间的所有提交(这应包括您的所有临时提交,仅包括那些提交):
git log --oneline $(git merge-base master HEAD)..HEAD
您可以将该命令的输出传递给wc -l
并获取提交次数,这是您git reset
命令所需的数量。
或者,您可以直接使用以下内容获取该号码:
git rev-list --count $(git merge-base master HEAD)..HEAD
全部放在一起:
git reset --soft HEAD~$(git log --oneline $(git merge-base master HEAD)..HEAD | wc -l)
或者:
git reset --soft HEAD~$(git rev-list --count $(git merge-base master HEAD)..HEAD)
执行重置后,不是将squash_branch
合并到dev
中,而是更好地进行硬重置(在您确认没有任何内容被破坏之后):
git checkout dev
git reset --hard squash_branch
此外,合并冲突往往是有原因的,所以我要小心翼翼地强行推进遥控器。如果必须强制推送,请改为执行此操作:
git push origin master --force-with-lease
--force-with-lease
标志将导致Git覆盖您已经提取的任何提交,但如果远程具有您不知道的新提交,该命令将失败。