Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在git中创建一个适当的合并提交,它也被压缩了_Git_Github_Merge - Fatal编程技术网

如何在git中创建一个适当的合并提交,它也被压缩了

如何在git中创建一个适当的合并提交,它也被压缩了,git,github,merge,Git,Github,Merge,我正试图解决我的git历史记录中的一个问题 我有两个分支,我们称它们为a和b,a是我的存储库的源分支,而b是从它分支出来的。许多合并的拉请求(合并提交和压缩提交的混合)发生在a,并且b没有重新设置基址,也没有针对b重新打开这些PRs。为了更新b,我(天真地)从a中挑选适用于b的合并提交 随着时间的推移,随着代码在a中的测试和批准,b现在等于a,差异为空,但历史显示,(正如预期的那样)提交存在差异。(b在Github中被视为在a之前提交的数量) 我想消除这种分歧,如果我执行从一个分支到另一个分支的

我正试图解决我的git历史记录中的一个问题

我有两个分支,我们称它们为
a
b
a
是我的存储库的源分支,而
b
是从它分支出来的。许多合并的拉请求(合并提交和压缩提交的混合)发生在
a
,并且
b
没有重新设置基址,也没有针对
b
重新打开这些PRs。为了更新
b
,我(天真地)从
a
中挑选适用于
b
的合并提交

随着时间的推移,随着代码在
a
中的测试和批准,
b
现在等于
a
,差异为空,但历史显示,(正如预期的那样)提交存在差异。(
b
在Github中被视为在
a
之前提交的数量)

我想消除这种分歧,如果我执行从一个分支到另一个分支的合并提交,我会得到一个长字符串的提交,没有任何更改(除了在Github上的某些情况下,它会变得混乱),这将污染任何一个分支的历史记录(如果允许的话)

e、 g.
git merge a
from
b
git merge b
from
a
在日志中显示一长串提交。(编辑:这是带有
--无ff

如果我执行挤压,我会收到一条很好的消息,列出那些没有更改的提交

e、 g.
git merge a--squash
from
b
git merge b--squash
from
a
需要
git commit--allow empty

但这并不能阻止“该部门领先/落后”的局面

因此,我的问题是如何生成单个提交(可以在任意一个分支中,也可以在两个分支中),以防止出现“前/后”情况


编辑:这主要是为了便于跟踪Github上发生的事情,我知道git是如何工作的,并且知道如何通过强制推动破坏一个或其他分支的历史来做到这一点,但我正试图以一种易于反思的方式保存这两个分支。

这里唯一的真正答案是,你没有

Git存储的是一个提交图。每个提交都有自己唯一的散列ID,此存储库或任何其他存储库中的任何其他提交都不会使用。1每个提交还指向(向后)其父提交;这就是形成图表的原因

也就是说,给定一个线性提交链,使用大写字母代表它们的实际大而丑陋的哈希ID,我们可以这样绘制它们:

... <-F <-G <-H ...
          I--J   <-- branch1
         /
...--G--H
         \
          K--L   <-- branch2
我们需要两个分支名称来查找所有提交,因为Git的工作原理是让一个分支名称指向最后一个提交,我们称之为“分支的一部分”。提交
J
branch1
上的最后一次提交
J
指向
I
,后者指向
H
。同时,名称
branch2
指向commit
L
,它指向
K
,它指向
H
。请注意,commit
H
位于两个分支上(commit
G
和更早版本也是如此)

如果
H
有一个指向它的名称:

          I--J   <-- branch1
         /
...--G--H   <-- master
         \
          K--L   <-- branch2
M
出来的多个向后箭头同时指向
J
L
,这意味着branch1现在比
branch2
早三次提交:从
branch1
我们可以到达提交
M
J
I
,以及
L
K
当然还有
H
和更早的版本。从
branch2
,我们可以到达
L
K
H
及更早,但我们不能从
H
前进到
I

使用
git merge--squash
,git将使用与merge
M
相同的内容进行新的提交,但不是两个向后箭头,而是只得到一个:

          I--J
         /    \
...--G--H      M   <-- branch1 (HEAD)
         \
          K--L   <-- branch2
如果没有可以用来查找commit
L
的名称,您将永远不会再看到它。因为commit
L
是您用来查找commit
K
的方法,所以您也不会再看到这个方法了。它们会在Git存储库中保留一段时间,确切的时间很难预测,因为这取决于仍然找到commit
L
的任何隐藏(仅限reflog)名称,以及维护
Git gc
命令清理未使用的提交并真正删除它们的时间。但是删除名称
branch2
会删除branch2 reflog,因此唯一可能仍然记得
L
原始哈希ID的reflog是
头的reflog

(如果您有其他的分支和/或标记名可以记住提交
L
和/或
K
,它们仍然可以通过这种方式找到,并且不会被
git gc
垃圾收集器收集。)

通常,在
git merge--squash
之后,正确的做法是删除另一个分支名称,并完全忘记那些提交曾经存在过


1从技术上讲,任何从未“相遇”的Git存储库都可以无害地重用彼此的ID。在实践中,他们无论如何都不会。一个Git对象拥有与某个Git对象相同的散列ID的几率,就其自身而言,为2160分之一。正因为如此,随着对象数量的增加,这种可能性会迅速增加,但当对象数量少于数万亿时,这种可能性仍然是10-17分之一。另见

随着时间的推移,
a
中的代码经过测试和批准,
b
现在等于a,差异为空,但历史表明,(正如预期的那样)提交存在差异。我想消除这种分歧,如果我执行从一个到另一个的合并提交,我会得到一个很长的提交字符串[…],这会污染历史

您在历史记录中有不同的提交,或者有相同的提交。你不能两全其美

          I--J
         /    \
...--G--H      M   <-- branch1 (HEAD)
         \
          K--L   <-- branch2
...--G--H--I--J--M   <-- branch1 (HEAD)
         \
          K--L   [abandoned]