如何让git push永久跳过来自详细分支的提交?
对于一次回购,我使用一个简单的脚本定期提交对文件的更改,以保留一个非常详细的非逻辑历史记录,这是我出于统计目的想要保留的(例如,我知道关于如何让git push永久跳过来自详细分支的提交?,git,git-branch,git-push,Git,Git Branch,Git Push,对于一次回购,我使用一个简单的脚本定期提交对文件的更改,以保留一个非常详细的非逻辑历史记录,这是我出于统计目的想要保留的(例如,我知道关于git-rebase,但我无论如何都想保留这个非逻辑历史记录)。目前,我正在提交一个单独的分支autocommit并使用它 git checkout master git merge --squash autocommit git commit git checkout autocommit git merge --ff-only master 对于“正确”
git-rebase
,但我无论如何都想保留这个非逻辑历史记录)。目前,我正在提交一个单独的分支autocommit
并使用它
git checkout master
git merge --squash autocommit
git commit
git checkout autocommit
git merge --ff-only master
对于“正确”,承诺保持主分支整洁,同时保持与自动提交分支的关系。所以我有这样的历史
| * 95e4189 Merge branch 'main' into autocommit
| |\
| |/
|/|
* | 040386a <= created via git merge --squash autocommit
| * 72bc5a5 autocommit
| * 9aaf5a6 autocommit
| * ea758c0 autocommit
| * 7ff1de8 autocommit
其中↓'
表示一个git merge--squash
,这意味着A3
不是M2
的父级,但只有M1
是,而A3'
只是合并回M2
,以便更好地跟踪连接。我想我想要的只是
M1--------------=> M2 ---> .... [master]
\ /
A1 -> A2 -> A3 -> A4 (or maybe A3' first merging M2 back) [autocommit]
但是,autocommit
分支中的A1
等提交都没有被推送。要了解可能的情况,了解一下git的工作原理是很有用的。从根本上说,git构建了分层的版本控制模型:
一种内容寻址数据库,在该数据库中,可以根据数据内容的散列查找任意数据块。这些blob是不可变的,因为更改任何内容都会导致新的散列,因此永远不会更新现有项
一种有向无环图,其中blob描述存储库的状态、一些元数据(日期、提交者、消息等)以及零个或多个父级。父项由它们的不可变散列寻址,而父项又是为新提交而散列的内容的一部分
指向特定提交的指针,以给它们提供更为用户友好的名称。我们称其中一些为“分支”,但它们只指向一个提交;从那里,git可以沿着父引用向后走,以找到“在”该分支上的所有提交
从这里,我们可以看到一些不可能的事情:
- 让您的本地副本记录一次提交的两个父项,但github只显示同一次提交的一个父项-不同的父项集将给出不同的哈希值,因此没有人会将其识别为同一次提交
- 记录了两个父级,但没有在
自动提交
分支上推送提交-git不知道它在历史记录中找到的合并中的分支名称,它只是将所有父级提交视为它向后跟踪的历史记录的一部分
- 推送可在一个分支上访问的所有提交,但也可在另一个分支上访问的提交除外。这仍然不是一个足够强的定义,因为最终您将在创建
autocommit
分支之前到达历史记录中的提交,git也不知道在历史记录中发生了什么
- 即使您可以定义不希望推送的提交列表,工具也不会很高兴找到一个显然不存在的对父提交的引用,并且可能会假设您的存储库已损坏
我真的只能想到两个选择:
- 从您的自动提交分支记录一个正常的合并,并在历史记录中显示自动提交
- 像现在一样挤压提交,但是创建自己的工具来记录挤压的自动提交,并允许您查找它们,确保没有遗漏任何内容,等等
涵盖了大多数可能性,但还有一种可能性,前提是您的“详细”和“非详细”分支始终在“更新非详细分支”点完全同步源代码,即:
o----------A----------B <-- master
\ ⋮\ ⋮\
D1--D2--D3-M1--D4--D5-M2 <-- detailed
由于没有从o
到o
的更改(o
是此合并的合并基础),Git将这些更改与详细的上的o
之后的更改“组合”。产生的非合并(挤压)提交是提交A
。但在提交A
后,我们立即运行:
git checkout detailed
git merge master
Git现在比较commito
vsA
来查看它们的变化,并比较o
vsD3
来查看我们的变化。这些更改完全匹配(当然),因此merge commitM1
有一个快照,该快照同时匹配提交D3
和a
我们现在在detailed
上进行更多的常规详细提交,然后重复上述过程来创建提交B
和M2
。这次的合并基础是提交A
。最终结果是,我们与提交A
时处于相同的位置,但下一次执行所有这些操作时,合并基础将是提交B
请注意,可以创建提交A
和B
,而无需运行git merge--squash
,无需运行git merge
,就可以创建合并M1
和M2
:我们知道每次提交所需的树,因此可以简单地使用git commit tree
进行这些提交。但是git commit tree
不是面向用户的命令,使用起来有点困难。您可以编写自己的Git命令来执行此操作,以确保所有操作都正确完成,例如,没有直接提交到master
,但是如果您使用Git merge--squash,直接提交到master
实际上就可以了。下面是其中一个可能的样子,表示为哈希ID为C
的提交:
o----------A----------B-----C----D <-- master
\ ⋮\ ⋮\ ⋮\
D1--D2--D3-M1--D4--D5-M2--D6--D7-M3 <-- detailed
o----A----B----C----D谢谢你的输入,我几乎担心你是对的……不确定我是否理解正确,但这不是我已经在使用的git merge--squash
策略吗?也许我遗漏了一个细节嗯,不,我认为你是对的,那是你已经在做的。
git checkout detailed
git merge master
o----------A----------B-----C----D <-- master
\ ⋮\ ⋮\ ⋮\
D1--D2--D3-M1--D4--D5-M2--D6--D7-M3 <-- detailed