【问题标题】:Some question about git rebase onto option关于 git rebase 到选项的一些问题
【发布时间】:2022-01-19 06:42:57
【问题描述】:

主分支:

百灵枝:

变基后 奇怪!,lark_file 在哪里?嗯,应该是三个文件(init、main_file、lark_file)吧?

创建环境的脚本。

#!/bin/env bash
git init
touch init
git add -- .
git commit -am init
echo a >> main_file
git add --all
git commit -am 'main a'
echo b >> main_file
git commit -am 'main b'
echo c >> main_file
git commit -am 'main c'
echo d >> main_file
git commit -am 'main d'
echo e >> main_file
git commit -am 'main e'

git checkout HEAD~5

git checkout -B lark
echo a >> lark_file
git add --all
git commit -am 'lark a'
echo b >> lark_file
git commit -am 'lark b'
echo c >> lark_file
git commit -am 'lark c'
echo d >> lark_file
git commit -am 'lark d'
echo e >> lark_file
git commit -am 'lark e'
echo f >> lark_file
git commit -am 'lark f'

【问题讨论】:

    标签: git rebase


    【解决方案1】:

    TL;DR:由于 rebase 的重命名检测,Git 将更改应用到错误的文件。 (--onto 标志不是获得此效果所必需的。您只需要有一个差异,在其中 Git 会产生错误/不正确的重命名。)

    首先,让我稍微修改一下您的复制器,以便每个人都可以使用它:

    $ cat repro.sh
    #! /bin/sh -e
    mkdir t
    cd t
    git init
    touch init
    git add -- .
    git commit -am init
    echo a >> main_file
    git add --all
    git commit -am 'main a'
    echo b >> main_file
    git commit -am 'main b'
    git tag tag-onto
    echo c >> main_file
    git commit -am 'main c'
    echo d >> main_file
    git commit -am 'main d'
    echo e >> main_file
    git commit -am 'main e'
    
    git checkout HEAD~5
    
    git checkout -B lark
    echo a >> lark_file
    git add --all
    git commit -am 'lark a'
    echo b >> lark_file
    git commit -am 'lark b'
    echo c >> lark_file
    git commit -am 'lark c'
    echo d >> lark_file
    git commit -am 'lark d'
    echo e >> lark_file
    git commit -am 'lark e'
    echo f >> lark_file
    git commit -am 'lark f'
    
    git rebase --onto tag-onto HEAD~3
    

    这有一些简单的变化:它在其中创建了一个临时目录 tcd-s,这样我们就可以在完成后删除临时目录,并且复制器脚本本身不会不要卡在存储库中。更有用的是,它将最后一个 git rebase 更改为:

    git rebase --onto tag-onto HEAD~3
    

    也就是说,我们删除了最终的HEAD——它毫无意义地产生了一个分离的 HEAD——我们使用标签 tag-onto 作为--onto 目标,我们将在该目标上复制lark d 提交.

    运行此脚本会重现该问题:

    $ ./repro.sh
    [much output snipped]
    CONFLICT (content): Merge conflict in main_file
    error: could not apply 1a3193f... lark d
    Resolve all conflicts manually, mark them as resolved with
    "git add/rm <conflicted_files>", then run "git rebase --continue".
    You can instead skip this commit: run "git rebase --skip".
    To abort and get back to the state before "git rebase", run "git rebase --abort".
    Could not apply 1a3193f... lark d
    

    这里的设置是我们尝试将提交 lark~2 挑选到提交 tag-ontomaster~3main~3 取决于您的初始分支)。

    我们需要意识到git cherry-pickgit merge的一种。它进行三向合并,合并基础是提交的父级。这意味着它运行两个git diffs,从父lark~3 到当前提交HEAD,从父lark~3 到提交lark~2。让我们看一下这两个差异中的第一个:

    $ git diff lark~3 HEAD
    diff --git a/lark_file b/main_file
    similarity index 66%
    rename from lark_file
    rename to main_file
    index de98044..422c2b7 100644
    --- a/lark_file
    +++ b/main_file
    @@ -1,3 +1,2 @@
     a
     b
    -c
    

    这表示我们应该重命名文件:现在应该将其命名为 main_file,而不是 lark_file

    第二个差异当然显示了您在提交 lark d 中添加的内容:

    $ git diff lark~3 lark~2
    diff --git a/lark_file b/lark_file
    index de98044..d68dd40 100644
    --- a/lark_file
    +++ b/lark_file
    @@ -1,3 +1,4 @@
     a
     b
     c
    +d
    

    所以 Git 决定我们需要将 lark_file 重命名为 main_file 并在末尾添加 d,同时从 main_file 的末尾删除 c

    这确实是 Git 所做的:我们现在有一个文件 main_file,而不是两个单独的文件 lark_filemain_file,我们看到了冲突。我的是diff3风格而不是merge风格,所以它有更多信息:

    $ cat main_file 
    a
    b
    <<<<<<< HEAD:main_file
    ||||||| parent of 1a3193f... lark d:lark_file
    c
    =======
    c
    d
    >>>>>>> 1a3193f... lark d:lark_file
    

    Git 的行为符合 Git 规则。

    Git 合并规则时不时会产生意外,这就是为什么您必须始终检查 任何 合并结果的原因。这包括挑选结果,即合并结果。

    【讨论】:

    • 好吧,樱桃采摘部分真的让我很困惑,我不得不说我没有遵循。
    • 樱桃挑选是一种合并形式。通过查找 三个 提交而不是两个提交来进行合并。这对于传统的合并更有意义,在这种合并中,您实际上是从一个共同的起点开始合并工作,但它也用于挑选樱桃。 Rebase 是重复挑选的,因此每个“复制提交”步骤都使用git cherry-pick。这就是所有这些的来源。要正确理解merging,你应该先进入merging这个话题。
    猜你喜欢
    • 2013-03-01
    • 1970-01-01
    • 2014-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-24
    • 2013-07-07
    相关资源
    最近更新 更多