假设我有两个分支A
,master
。
现在在分支A中我有这些提交
a
b
c
d
e
然后用户压缩了提交,我不知道怎么但昨天在他的分支上我能够看到5 commits
今天我只看到1 commit with message squashed commits
现在我想问一下,在压扁之前,我从hi分支创建新的分支
git checkout -b B-backup
答案 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做的是复制提交D
,E
和C
。我们拨打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 --all
和git 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仓库,有两个分支:master
和new_branch
。
new_branch
是在5次单独提交后创建的:a.txt
,b.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
即使原始分支的历史记录发生变化,您的备份也会保留其提交历史记录。