shr*_*ans 6 git merge github rebase
我最近拆除了另一个开发人员正在处理的远程分支,让我们称之为feature
.然后我犯了一个错误,就是做了一个反思develop
- 主要的工作分支 - 我现在已经知道这是你不应该做的事情.该feature
分支已合并为develop
.
我现在develop
遇到的问题是有一个奇怪的Git历史.所有提交feature
似乎都是重复的,它们出现了两次.但是,它们具有不同的提交ID.
我的历史现在看起来有点像这样(ID用于演示目的):
0007 commit from feature #3 <--- these commits are duplicated
0006 commit from feature #2
0005 commit from feature #1
0004 different commit from another branch #2
0004 different commit from another branch #1
0002 commit from feature #3
0002 commit from feature #2
0001 commit from feature #1
Run Code Online (Sandbox Code Playgroud)
我犯了一个愚蠢的错误!我能做些什么吗?历史看起来很难看,但所有正确的代码似乎都存在.我可以删除重复的提交吗?或者还有其他方法来清理历史吗?
请为经验较少的Git用户写下你的答案.
tor*_*rek 10
"复制提交"就是这样git rebase
做的.它复制了一些提交,然后将分支指针混乱,以便"忘记"或"放弃"原始提交.(但见下文.)
这是一个如何git rebase
复制的说明.单个字母表示提交,右侧的名称是分支名称,实际上只指向一个提交,即"分支的尖端".每个提交都指向它的父提交,即A--B
连接线实际上是指向左箭头(对角线也是左边的箭头,对于早期的提交,后面的提交是向右):
C--D <-- branch1
/
A--B
\
E <-- branch2
Run Code Online (Sandbox Code Playgroud)
这是"之前"图片,您只有"原始"提交.现在,您决定git checkout branch1
并git rebase branch2
让C
和D
来之后 E
.但Git实际上根本无法改变原始版本C--D
,因此它将它们复制到新的副本中,C'
并且新的副本D'
略有不同:它们之后E
(并且还使用您所做的任何代码更改E
):
C--D [abandoned]
/
A--B
\
E <-- branch2
\
C'-D' <-- branch1
Run Code Online (Sandbox Code Playgroud)
C--D
在这里完全忘记原件会好的,但如果你认为这毕竟是一个坏主意怎么办?rebase将分支的原始值保留在"reflogs"中以记住它.它还使用特殊名称ORIG_HEAD
.这更容易使用,但只有一个 ORIG_HEAD
,而有可能无限数量的reflog条目.Reflog条目默认保留至少30天,让您有时间改变主意.回头看第二张图并假设ORIG_HEAD
已添加.
现在,您遇到的问题是因为它不仅仅是记住以前提交的分支名称.每个提交还会通过那些连接的左箭头记住它自己以前的提交.所以,让我们看看如果有另一个名称,或其他(合并)提交,记住C
和,会发生什么D
.例如,如果我们有这个更复杂的起始图怎么办?
.-----F <-- branch3
/ /
/ C--D <-- branch1
/ /
A--B
\
E <-- branch2
Run Code Online (Sandbox Code Playgroud)
如果我们现在"改变" branch1
,我们得到这个:
.-----F <-- branch3
/ /
/ C--D [ORIG_HEAD and reflog]
/ /
A--B
\
E <-- branch2
\
C'-D' <-- branch1
Run Code Online (Sandbox Code Playgroud)
Commit F
是一个合并提交:它指向提交A
和提交D
.所以它保留了原件D
,保留了原件C
,给我们带来了一团糟.
F
可能是一个普通的普通提交,仅指向D
,我们会看到同样的问题.平原普通提交更容易复制,但是,如果F
是不合并,如果我们的F
尖回来才D
,而不是A
-我们可以仔细地重订branch3
为好,复制F
到F'
其中F'
之后新的来D'
.也可以重新进行合并,但这有点棘手(不是F
正确复制就是这么简单 - 很容易"迷路"并且错误地C--D
再次复制).
每当您复制您或其他人提交的提交时,您将遇到此问题,并且您和"其他人"(可能是"其他人")也仍在使用原件.这发生在我们的提交中F
,例如:我们仍在使用原始C--D
链.我们可以通过创建一个新的F'
并使用它来解决这个问题,只要我们是唯一使用它的人branch3
.但是,如果branch3
被公布,或者在这方面,如果我们公布了branch1
,让其他人可能有他们作为origin/branch1
或者origin/branch3
,我们已经失去了控制权的原件C--D
.
因此,标准建议是仅重新私有(未发布)提交,因为你知道谁在使用它们 - 当然只是你 - 你可以自己检查并确保你没有使用它们,或者可以复制它们因为你还计划复制或以其他方式重新提交像F
.
如果你已经完成了rebase制作的副本并将它们发布(将它们推送到origin
),那么你就会陷入困境.无论如何,你可以"撤销"你的rebase,并请求所有共享使用的人origin
,以确保他们不会使用你的C'-D'
类型副本,因为你正在放回原件.
(对于更高级的用户组,您甚至可以同意某些分支机构定期进行重新定位,并且您和他们必须都知道何时发生这种情况,然后所有人都会注意切换到新的提交副本.但是,这可能不是你现在想要做的!)
所以,如果你(a)可以和(b)想要 "撤消"你的rebase,现在reflog或者保存的ORIG_HEAD
,真的会派上用场.让我们再看第二个例子,看看我们忘记了branch3
仍然记得原始C-D
提交后我们有什么:
.-----F <-- branch3
/ /
/ C--D [ORIG_HEAD and reflog]
/ /
A--B
\
E <-- branch2
\
C'-D' <-- branch1
Run Code Online (Sandbox Code Playgroud)
现在,假设我们branch1
从底行删除名称并写入一个新的<-- branch1
指向commit D
:
.-----F <-- branch3
/ /
/ C--D <-- branch1
/ /
A--B
\
E <-- branch2
\
C'-D' [abandoned]
Run Code Online (Sandbox Code Playgroud)
现在我们已经放弃了C'-D'
,只是停下来看看它.将此图表与原始图表进行比较,瞧!那正是你想要的!
以这种方式"移动"分支标签的命令是git reset
(它移动当前分支,因此您必须打开branch1
).D
在reflog中查找原始提交哈希,或检查ORIG_HEAD
是否正确,或使用reflog拼写来识别提交D
.(对于新手,我发现原始哈希的剪切和粘贴是要走的路.)例如,尝试:
$ git log --graph --decorate --oneline ORIG_HEAD
Run Code Online (Sandbox Code Playgroud)
看看ORIG_HEAD
你是否得到了正确的哈希.如果没有,请尝试git reflog branch1
(查看branch1
此处的特定reflog )查找哈希值,然后使用:
$ git log --graph --decorate --oneline branch1@{1}
Run Code Online (Sandbox Code Playgroud)
(或者剪切并粘贴原始哈希而不是使用branch1@{1}
).一旦找到所需的"原始"提交,您就可以:
$ git status # to make sure you're on the right branch
# and that everything is clean, because
# "git reset --hard" wipes out in-progress work!
$ git reset --hard ORIG_HEAD
Run Code Online (Sandbox Code Playgroud)
(或者放入branch1@{1}
原始哈希ID,代替ORIG_HEAD
原样).1 移动当前分支(我们刚检查过),使其指向给定的提交(branch1@{1}
来自reflog,或ORIG_HEAD
原始哈希ID),以使我们得到最终的图形.该--hard
套了我们的指数/舞台区,我们的工作树,以符合新的承诺,我们刚重新指向我们的分公司.
1这里的一般想法,一直在Git中重复出现,我们必须命名一些特定的提交,如果有必要,Git会从中找到其余的提交.任何名称都可以使用:分支名称,名称,类似HEAD
的reflog名称master@{1}
或原始提交哈希ID.Git并不真正关心你如何告诉它"看看这里提交"; 最终,Git将该名称解析为那些丑陋的SHA-1哈希ID,然后使用它.
归档时间: |
|
查看次数: |
3775 次 |
最近记录: |