首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Git变换重基

Git变换重基
EN

Stack Overflow用户
提问于 2017-04-06 23:22:03
回答 2查看 53关注 0票数 4

我有三个分支:主人,特征,修正.提交如下所示:

代码语言:javascript
复制
    4-5-6(feature)
    |
1-2-3(master)
    |
    7(bugfix)

我做了"git rebase bugfix特性“来用bugfix测试我的特性。

代码语言:javascript
复制
    1-2-3(master)
        |
        7(bugfix)-4-5-6(feature)

现在,我需要为我的特性分支创建一个不带the的拉请求,所以我做了"git重基主特性“,并期望:

代码语言:javascript
复制
1-2-3(master)-4-5-6(feature)
    |
    7(bugfix)

相反,它说功能是最新的与主人。这是真的,但我不想在那里合并commit 7。我可以进行重基、交互式和删除该提交,但我想知道是否有更好的方法来做到这一点。我以为重基只会将一个分支中的提交传递给另一个分支,但看起来并非如此。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-06 23:39:52

需要认识到的是,重基不会重写历史或移动提交,在Git中提交是不能更改的。相反,它创造了新的历史,并说它一直是这样的。例如,当您开始时:

代码语言:javascript
复制
    4-5-6(feature)
    |
1-2-3(master)
    |
    7(bugfix)

然后,git rebase bugfix feature,真正发生的是:

代码语言:javascript
复制
    4-5-6
    |
1-2-3(master)
    |
    7(bugfix)-4A-5A-6A(feature)

作出三项新的承诺: 4A、5A和6A。最初的提交仍然存在,但没有指向它们。它们最终会被清理干净,但它们会在那里呆上几天。

这意味着你可以撤销一个重基,这就是你想要做的。您需要找到feature在重基之前的位置。这可以用git reflog来实现,它每次跟踪HEAD的移动。这种情况发生在checkoutcommitresetrebase上。git reflog可能类似于:

代码语言:javascript
复制
65e93ca (HEAD -> feature) HEAD@{0}: rebase finished: returning to refs/heads/feature
65e93ca (HEAD -> feature) HEAD@{1}: rebase: 3 feature
6d539a3 HEAD@{2}: rebase: 2 feature
3cd634f HEAD@{3}: rebase: 1 feature
b84924b (bugfix) HEAD@{4}: rebase: checkout bugfix
a9fd2f1 HEAD@{5}: commit: 3 feature
29136bc HEAD@{6}: commit: 2 feature
60543b0 HEAD@{7}: commit: 1 feature
c487530 (master) HEAD@{8}: checkout: moving from master to feature

这就告诉我,a9fd2f1是在重新构建功能之前最后一次提交功能。与其重做重基,我只需将功能移回。

代码语言:javascript
复制
git checkout feature
git reset --hard a9fd2f1

在将来,如果您在进行重基之前对特性的原始位置进行git tag,这类事情就会变得容易得多。然后,您可以git reset返回到该标记,而不必搜索重发。

至于您的具体问题,问题是在重新基础之后,您的存储库现在如下所示:

代码语言:javascript
复制
6A [feature]
|
5A
|
4A
|
7 [bugfix]
|
3 [master]
|
2
|
1

当您问git rebase master feature时,Git注意到主人已经是特性的祖先,什么也不做。不重要的是,错误是中间的。

相反,您需要告诉Git,您只想重基4A、5A和6A,而忽略7,这是使用--onto语法完成的。

代码语言:javascript
复制
git rebase --onto master bugfix feature

这意味着重新定位,但不包括,错误修复功能的主人。

我建议使用git reset,而不是尝试重做重基。不能保证第二次重新基地也会出现同样的情况,特别是如果有冲突的话。然而,使用git reset,您将显式地移回存储库的旧状态。

票数 2
EN

Stack Overflow用户

发布于 2017-04-06 23:45:33

我以为重基只会将一个分支中的提交传递给另一个分支,但看起来并非如此。

这是关键:图中的提交7位于分支feature中。它也在bugfix分支中。提交1-2-3在所有三个分支中。

Git的分支与大多数其他版本控制系统有很大的不同。分支“包含”提交只是因为它能够“到达”从分支名称所指向的提交。像masterbugfixfeature这样的分支名称只是指向一个特定的提交,Git称之为分支的尖端。通过让每个提交“指向”它的前身,提交本身形成了一个链。

正因为如此,git rebase实际上复制了提交:您从:

代码语言:javascript
复制
        4--5--6   <-- feature
       /
1--2--3      <-- master
       \
        7      <-- bugfix

至:

代码语言:javascript
复制
        4--5--6   [abandoned - used to be feature]
       /
1--2--3      <-- master
       \
        7      <-- bugfix
         \
          D--E--F   <-- feature

如果D是原始4的副本,E5的副本,F6的副本(我在这里使用了第4、第5和第6个字母,以便如果我们愿意,可以将7复制到G,但是这种技术即将耗尽)。

不过,你还是可以得到你想要的。您只需要再次复制D-E-F,或者--对于这个特殊情况来说,这可能更好--回到废弃的、原始的4-5-6

当您使用git rebase复制提交时,原始文件保持不变。您可以通过两个名称找到它们:ORIG_HEAD和reflog名称。名称ORIG_HEAD被其他各种命令覆盖,但是您可以检查它是否仍然指向提交6

代码语言:javascript
复制
git log ORIG_HEAD

你可能会认出你的原作。

reflog名称的形式为name@{number},,例如,feature@{1}number部件每次更改name部件所指向的提交时都会增加,因为Git只是将name的当前值保存在reflog中,从而使其余部分都提高了一个档次。

因此:

代码语言:javascript
复制
git log feature@{1}

应该向您展示与git log ORIG_HEAD相同的提交,除了feature@{1}停留时间更长(可能成为feature@{2}feature@{3}等)。默认情况下,每个名称的前一个值保存至少30天,因此应该有足够的时间将其取回。

要将其返回,请使用git reflog feature查看@{...}部件中的数字,然后在feature (git checkout feature)上运行:

代码语言:javascript
复制
git reset --hard feature@{1}

或者不管数字是什么(尽管首先用git log再次验证是个好主意)。

(这假设您没有任何要签入的内容,即git status说一切都是干净的,因为git reset --hard删除了尚未签入的索引和工作树更改。)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43267275

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档