让我们说:
A B C
)。A B C
)已经消失了。git cherry-pick
仅选择我们后面想要的提交),但他不能完全记住。 A B C
。他们看起来像是从大师那里成功迁移过来的。鉴于上述情况,有谁可以解释为什么git丢失了这些变化? (我的个人理论是git不知怎的"记得"我们已经撤消了提交A B C
,所以当他们来自新功能分支时,git决定不合并它们。编辑:对不起,如果这个解释听起来太像魔法思维了,但我感到很茫然。我欢迎任何尝试用更多技术术语来解释这个问题,如果它是对的话。
很抱歉无法提供更多详细信息,但我个人没有在回购邮件中进行这些更改,因此无法详细说明所做的事情。
编辑:好的,正如这里建议的那样,我让我的同事在他的机器上执行git reflog
,所以我在这里粘贴结果。要回到我以前的(链接)问题,我们有一个这样的树:
A - B - C - D - E - F master
\
\- G - H new feature branch
我们希望将B和C移动到新功能分支。
所以,他发给我的git reflog
就在这里。提交5acb457
将对应于"提交A"在上图中:
4629c88 HEAD@{59}: commit: blah
f93f3d3 HEAD@{60}: commit: blah
57b0ea7 HEAD@{61}: checkout: moving from master to feature_branch
4b39fbf HEAD@{62}: commit: Added bugfix F again
4fa21f2 HEAD@{63}: commit: undid checkouts that were in the wrong branch
1c8b2f9 HEAD@{64}: reset: moving to origin/master
5acb457 HEAD@{65}: checkout: moving from 5acb4576eca4b44e0a7574eea19cca067c039dc5 to master
5acb457 HEAD@{66}: checkout: moving from master to 5acb4576eca4b44e0a7574eea19cca067c039dc5
1c8b2f9 HEAD@{67}: checkout: moving from 1c8b2f9bf54ca1d80472c08f3ce7d9028a757985 to master
1c8b2f9 HEAD@{68}: rebase: checkout master
5acb457 HEAD@{69}: checkout: moving from master to 5acb4576eca4b44e0a7574eea19cca067c039dc5
1c8b2f9 HEAD@{70}: checkout: moving from 5acb4576eca4b44e0a7574eea19cca067c039dc5 to master
5acb457 HEAD@{71}: checkout: moving from master to 5acb4576eca4b44e0a7574eea19cca067c039dc5
1c8b2f9 HEAD@{72}: merge origin/master: Fast-forward
5acb457 HEAD@{73}: checkout: moving from master to master
5acb457 HEAD@{74}: checkout: moving from 5acb4576eca4b44e0a7574eea19cca067c039dc5 to master
5acb457 HEAD@{75}: checkout: moving from undo_branch to 5acb4576eca4b44e0a7574eea19cca067c039dc5
5acb457 HEAD@{76}: checkout: moving from master to undo_branch
1c8b2f9 HEAD@{77}: checkout: moving from undo_branch to master
525dbce HEAD@{78}: cherry-pick: Bugfix F
a1a5028 HEAD@{79}: cherry-pick: Bugfix E
32f8968 HEAD@{80}: cherry-pick: Feature C
8b003cb HEAD@{81}: cherry-pick: Feature B
5acb457 HEAD@{82}: checkout: moving from 5acb4576eca4b44e0a7574eea19cca067c039dc5 to undo_branch
5acb457 HEAD@{83}: checkout: moving from master to 5acb4576eca4b44e0a7574eea19cca067c039dc5
1c8b2f9 HEAD@{84}: checkout: moving from 1c8b2f9bf54ca1d80472c08f3ce7d9028a757985 to master
1c8b2f9 HEAD@{85}: pull origin HEAD:master: Fast-forward
5acb457 HEAD@{86}: checkout: moving from master to 5acb4576eca4b44e0a7574eea19cca067c039dc5
5acb457 HEAD@{87}: reset: moving to 5acb4576eca4b44e0a7574eea19cca067c039dc5
1c8b2f9 HEAD@{88}: merge origin/master: Fast-forward
5acb457 HEAD@{89}: reset: moving to 5acb4576eca4b44e0a7574eea19cca067c039dc5
1c8b2f9 HEAD@{90}: checkout: moving from 5acb4576eca4b44e0a7574eea19cca067c039dc5 to master
5acb457 HEAD@{91}: checkout: moving from master to 5acb4576eca4b44e0a7574eea19cca067c039dc5
1c8b2f9 HEAD@{92}: merge origin/master: Merge made by the 'recursive' strategy.
7b912cd HEAD@{93}: checkout: moving from 7b912cdf33843d28dd4a7b28b37b5edbe11cf3b9 to master
7b912cd HEAD@{94}: cherry-pick: Bugfix F
df7a9cd HEAD@{95}: cherry-pick: Bugfix E
d4d0e41 HEAD@{96}: cherry-pick: Feature C
701c8cc HEAD@{97}: cherry-pick: Feature B
5acb457 HEAD@{98}: checkout: moving from master to 5acb4576eca4b44e0a7574eea19cca067c039dc5
22ecc3a HEAD@{99}: checkout: moving from 5acb4576eca4b44e0a7574eea19cca067c039dc5 to master
5acb457 HEAD@{100}: checkout: moving from master to 5acb4576eca4b44e0a7574eea19cca067c039dc5
22ecc3a HEAD@{101}: commit: bugfix E
3b568bc HEAD@{102}: checkout: moving from feature_branch to master
57b0ea7 HEAD@{103}: commit: blah
152c5b9 HEAD@{104}: checkout: moving from master to feature_branch
3b568bc HEAD@{105}: commit: bugfix D
fe3bbce HEAD@{106}: checkout: moving from feature_branch to master
152c5b9 HEAD@{107}: commit: blah
2318ebc HEAD@{108}: commit: blah
cc5ea32 HEAD@{109}: commit: blah
a5c2303 HEAD@{110}: commit: blah
544a99a HEAD@{111}: commit: blah
299f86a HEAD@{112}: commit: Feature G
fe3bbce HEAD@{113}: checkout: moving from master to feature_branch
fe3bbce HEAD@{114}: commit: Feature C
3852e71 HEAD@{115}: commit: Feature B
5acb457 HEAD@{116}: merge origin/master: Fast-forward
任何人都可以连续了解这4个cherry-pick
吗?我怀疑他并没有真正做git cherry-pick master~3
事,尤其不是~3
部分(当我第一次看到它时,它确实让我失望)。
答案 0 :(得分:3)
提交A,B和C失败的原因,那是因为这是您与同事共享的链接。让我们通过下面的图表说明:
<强> 1。假设您的同事做的原始提交历史,
...X---A---B---C---D---E master
<强> 2。将A
,B
和C
移至feature
分支。因此,您的同事从主人创建了一个新的feature
分支(提交E
}或任何提交。并通过以下步骤进行改造:
git checkout -b feature
git cherry-pick master~5 master~2
...X---A---B---C---D---E master
\
A'---B'---C' feature
第3。修改master
分支,
git checkout X
git cherry-pick master~2..master
git branch -f master
git checkout master
提交结构如下所示:
...X---D---E master
\
A'---B'---C' feature
所以直接原因是命令git cherry-pick master~2..master
。它将直接在提交D
上重新提交E
和X
,因此您无法在主分支上找到A
,B
和C
基于git flog
,似乎这些HEAD信息不足以显示您的同事所做的事情。 feature
分支似乎从提交C
而不是D
结帐
3b568bc HEAD@{105}: commit: bugfix D
fe3bbce HEAD@{106}: checkout: moving from feature_branch to master
152c5b9 HEAD@{107}: commit: blah
2318ebc HEAD@{108}: commit: blah
cc5ea32 HEAD@{109}: commit: blah
a5c2303 HEAD@{110}: commit: blah
544a99a HEAD@{111}: commit: blah
299f86a HEAD@{112}: commit: Feature G
fe3bbce HEAD@{113}: checkout: moving from master to feature_branch
fe3bbce HEAD@{114}: commit: Feature C
所以结构应该是:
A---B---C---D---E master
\
G---H feature
如果您只想更改提交结构,请执行以下操作:
A ---D---E master
\
B---C---G---H feature
您可以将master
分支和feature
分支重置为原始分支,然后在master
分支上重新提交提交,详细信息如下:
git checkout master
git reset --hard <original commit id for E>
git checkout feature
git reset --hard <original commit id for H>
git checkout master
git checkout <commit id for A>
git cherry-pick master~4..master~2 #To make the commits as A---D---E (drop B and C)
git branch -f master
git checkout master
答案 1 :(得分:0)
你已经得到了很长很好的答案。让我补充一点:
我的个人理论是git不知怎的&#34;记得&#34;我们撤消了提交A B C,所以当他们来自新功能分支时,git决定不合并它们。
Git从来没有&#34;不知何故&#34; &#34;记得&#34;关于存储库内容的任何信息。根据你之前所做的事情,它也决定不做或不做任何事情。在这方面它非常干净。它的所有命令都只是工具,可以处理其提交的有向非循环图(以及较低级别,它存储的所有其他对象)正在构建。为了使它更容易,它只会添加东西,永远不会改变或删除任何东西。
除了提交(即作者,时间戳,父提交等),树(即目录),blob(即二进制数据)和一些不那么重要的事物之外,实际上没有数据结构或进一步的管理信息关于你的文件等在存储库中。合并提交不会留下任何特定于&#34; merge&#34 ;;的信息。它只是一个多父母的提交。
当然没有任何神奇的,无证件的东西在继续。存储库是非常开放的,您可以使用git命令逐字查看所有内容,并且所有内容都已完整记录(google&#34; git数据结构&#34;或者#34; git internals&#34;如果您感兴趣的话)。如果您愿意,甚至修改内部对象也很容易。
有一点位保留历史信息,这就是所谓的&#34; rerere缓存&#34;它存储以前的冲突解决方案,因此确实可以改变未来合并的行为。确实非常方便,但默认情况下未启用,当然与手头的主题无关。
编辑:对不起,如果这个解释听起来太像魔法思维&#34;,但我不知所措。如果正确的话,我欢迎任何尝试用更多技术术语来解释这个问题
相信来源,卢克。很高兴您正试图让自己的头脑周围的git,并坚信一切都是平淡无奇的应该有所帮助,希望如此。