压缩提交是否也会删除其他分支的单个提交

时间:2014-01-21 00:56:38

标签: git version-control

假设我有两个分支Amaster

现在在分支A中我有这些提交

a b c d e

然后用户压缩了提交,我不知道怎么但昨天在他的分支上我能够看到5 commits

今天我只看到1 commit with message squashed commits

现在我想问一下,在压扁之前,我从hi分支创建新的分支

git checkout -b B-backup

然后那些个人提交将在备用分支中存在,或者如果他将来压制它们也会消失

2 个答案:

答案 0 :(得分:3)

这里涉及的git的一般原则可以回答你的问题:

  • 提交是永恒不变的:它们永远不会改变,永远不会被删除。
  • 但是,有一个例外:有时它们会被删除。

为了得到答案,我们必须检查一个例外。

存储库中的提交可以表示为"有向无环图" (DAG),每个提交列出其父提交。新存储库中的第一个提交是" root"提交并且没有父母,并且通常,每个后来的提交都有一个父(一个"常规"提交)或两个或多个("合并"提交)。因此,当您创建存储库及其初始提交时,您有一个没有父提交的提交节点,以及指向一个提交的分支标签master

o       <-- master

如果然后添加新提交,则有两个节点; master指向第二个,第二个指向第一个:

o<--o   <-- master

请注意,提交不会列出他们的孩子。那些必须动态发现。在这里,我们从master开始,然后向后工作。

如果我们添加一个新的分支A,从初始提交开始,并向该分支添加新的提交,它现在可能看起来像这样:

o<--o   <-- master
^
 \--o   <-- A

(请注意,根提交没有更改,因为它不必更改:最新提交将根列为其父级,但根不会将最新提交列为子级-commit。这会强制git动态发现分支图,但意味着提交可以永久保持不变。)

如果提交永远不会改变,那么你应该问:做什么改变了?显然,可以添加新的提交。为了能够找到那些新的提交,其他东西也必须改变,而其他东西是分支标签

分支标签移动

每当您向存储库添加新提交时,当前分支标签 - HEAD告诉git的分支标签#34;&#34; on&#34 ;;你在分行master&#34;&#34;当且仅当HEAD 时你才会对它(HEAD目录中有一个名为.git的实际文件) - 自动移动到点到新的提交。所以给出:

o--o   <-- master
 \
  o   <-- HEAD=A

(同样的图纸,我只是不再尝试输入箭头了,我已经在HEAD分支A上添加HEAD说&#34;的想法#34;),当你进行新的提交时,它进入A所说的位置,并且分支标签o--o <-- master \ o--o <-- HEAD=A 移动:

o--o   <-- master
 \
  o--o--o--o--o   <-- HEAD=A

当您添加更多提交时,分支标签也会继续移动:

HEAD

如果您添加&#34;合并&#34;提交时,分支标签仍然向前移动,但仍然只有只有一个o--o <-- master \ `-----------. o--o--o--o--o--o <-- HEAD=A 移动:

master

这里A仍然指向相同的旧提交;我们刚刚将其合并到rebase

某些步骤会复制

当你A--B <-- master \ C--D--E <-- HEAD=branch 分支时,git会生成旧提交的副本。让我们说我们有一个新的,不同的回购,看起来像这样:

o

(而不是提交节点的小git rebase -i master个字符,这次我使用了字母标签。假设您执行branch到&#34;移动&#34; B中的提交链,以便它#34;脱离&#34;提交A而不是提交C。在这种情况下,git做的是复制提交DEC。我们拨打C'A--B <-- master | \ \ C'-D'-E' <-- HEAD=branch | C--D--E [no label: "abandoned"] 的副本,依此类推。

旧的提交仍然存在,因为它们不可变且(几乎)永远存在:

git fsck

但是,像往常一样,git将分支标签移动到指向副本上的新的最新提交(&#34;提示&#34;提交)。

旧的提交链仍然存在;它不再有标签了。

这使链条符合&#34;垃圾收集&#34;。

未标记(未引用)提交最终被垃圾收集

&#34;未引用的&#34; commit是只能通过git gc之类的东西找到的,它会扫描整个存储库以查找其中的所有内容。当没有分支或标签标签时,仍然可以通过git调用&#34; reflogs&#34;进行引用,但reflog条目到期(默认情况下为30到90天,基于各种配置设置) )。

因此,在一个月左右的时间之后,在分支机构上提交过一次&#34;但是已经被放弃,进行垃圾收集。 (命令git reflog进行收集;默认情况下,各种其他git命令将根据需要自动调用它。)

但是,在收集它们之前的任何时候,您都可以添加对旧分支的提示的引用并阻止此收集。这包括在之前通常&#34;通常&#34;分支标签被移动。


因此,简短的答案是&#34;是的,他们将在备份分支中。&#34;

即使你没有提前创建备份分支,如果你曾经有过提交,你可能仍然将它们放在你的reflog中,你可以用git reflog branch找到它们(尝试git reflog --allgit reflog以及普通$ git reflog branch 222c4dd branch@{0}: reset: moving to origin/branch 9c0d6ac branch@{1}: commit: adjust file foo for stuff 222c4dd branch@{2}: reset: moving to origin/branch fb45c22 branch@{3}: reset: moving to HEAD^ 222c4dd $ git log --oneline 9c0d6ac [snip - let's say I decide that's the one I want] $ git branch resurrect 9c0d6ac )。然后,您可以为它们附加一个标签,使它们比默认的reflog到期时间更长:

git reflog

旧的提交现在已经复活了#34; (并且&#34;常规&#34; git命令可见,而不只是git log --walk-reflogs或{{1}})。

答案 1 :(得分:0)

备份分支中的个人提交仍然存在。 @ torek的答案很详细。这是一个快速创建的git仓库,有两个分支:masternew_branch

new_branch是在5次单独提交后创建的:a.txtb.txt ... e.txt在每次提交中。

我切换到master并压缩最后4次提交。它创建了一个新的提交,master已经向前推进了一次提交:

GitLab$ git branch
* master
new_branch

GitLab esarupa$ git log
commit 8ce95c8d369b0f6ede43a6fc073ff84660a43773
b,c,d,e

commit edd73ce559ffc1276ae0adba1cf9cfda080162f9
a.txt

现在,切换到new_branch并查看日志。

GitLab esarupa$ git log
commit 5d75559fbdaedee3b73a9b26f0ffcf87c37de7be
e.txt

commit 7ede26f50b0ffda58af8d32320e4f1e9dcc60a68
d.txt

commit a58d8ffcfd401c890df1fbe4c37142c4b0a53942
c.txt

commit 06fa5d9f21fb5759bae67547d802a31ad5112e7b
b.txt

commit edd73ce559ffc1276ae0adba1cf9cfda080162f9
a.txt

即使原始分支的历史记录发生变化,您的备份也会保留其提交历史记录。