如何解决;“由我们添加”;git cherry pick冲突?

如何解决;“由我们添加”;git cherry pick冲突?,git,git-cherry-pick,git-merge-conflict,Git,Git Cherry Pick,Git Merge Conflict,在一次樱桃采摘后的冲突解决过程中,我遇到了git的问题。问题涉及对上次提交中的git mv文件所做的修改 下面是要复制的完整命令的示例: mkdir git_repository && cd git_repository git init echo "foo" > myFooFile git add myFooFile git commit -m "First commit add myFooFile" git checkout -b branch-a rm myFoo

在一次樱桃采摘后的冲突解决过程中,我遇到了git的问题。问题涉及对上次提交中的
git mv
文件所做的修改

下面是要复制的完整命令的示例:

mkdir git_repository && cd git_repository
git init
echo "foo" > myFooFile
git add myFooFile 
git commit -m "First commit add myFooFile"

git checkout -b branch-a
rm myFooFile
echo "bar" > myBarFile
git add -A
git commit -m "rm myFooFile add myBarFile"

git checkout master
git mv myFooFile myBarFile
git add -u
git commit -m "git mv myFooFile myBarFile"
现在让我们对分支a进行修改

git cherry-pick $(git show-ref branch-a)
>error: could not apply 70c80f3... rm myFooFile add myBarFile
>hint: after resolving the conflicts, mark the corrected paths
>hint: with 'git add <paths>' or 'git rm <paths>'
>hint: and commit the result with 'git commit'
git cherry pick$(git show ref branch-a)
>错误:无法应用70c80f3。。。rm myFooFile添加myBarFile
>提示:解决冲突后,标记更正的路径
>提示:使用“git add”或“git rm”
>提示:并使用“git commit”提交结果
冲突如下:

git status
>On branch master
>You are currently cherry-picking commit 70c80f3.
>  (fix conflicts and run "git cherry-pick --continue")
>  (use "git cherry-pick --abort" to cancel the cherry-pick operation)
>
>Unmerged paths:
>  (use "git add <file>..." to mark resolution)
>
>   added by us:     myBarFile
>
>no changes added to commit (use "git add" and/or "git commit -a")
git状态
>论分行行长
>您当前正在提交70c80f3。
>(修复冲突并运行“git cherry pick--continue”)
>(使用“git cherry pick--abort”取消cherry pick操作)
>
>未合并路径:
>(使用“git add…”标记分辨率)
>
>由我们添加:myBarFile
>
>未向提交添加任何更改(使用“git add”和/或“git commit-a”)
不幸的是,执行
git add myBarFile
然后
git cherry pick--continue
不是解决方案,因为它会创建一个空提交

在解析过程中使用
git rm myBarFile
并不是更好,因为它会创建一个commit,从myBarFile中删除foo

如何正确地修复我们添加的cherry pick冲突,并最终在我的主分支上得到这3个承诺

  • rm myFooFile添加myBarFile
  • git mv myFooFile myBarFile
  • 第一次提交添加myFooFile
使用包含bar的myBarFile

注意:我知道我可以在git冲突解决过程中使用git checkout branch-a--myBarFile,但这不是我想要的解决方案,因为我认为这不是git的方式。

次要:不要这样做:

git cherry-pick $(git show-ref branch-a)
改为这样做:

git cherry-pick branch-a
cherry pick命令接受任何标识修订甚至修订范围的内容,如中所述。git show ref命令同时输出散列ID和名称,因此会尝试两次选择提交。(幸运的是,
git cherry pick
足够聪明,可以消除多余的部分。)

解决冲突的顶层视图 解决冲突没有单一的正确方法。你可以用任何你喜欢的东西。这里有几件重要的事情需要记住:

  • Cherry picking本质上是一个三向合并la
    git merge
    ,不同的是git没有找到实际的合并基,而是使用Cherry picking的提交的父级作为合并基(当然,最后的提交是常规的非合并提交)

  • Git不跟踪文件名的更改。相反,在执行包含cherry pick Git的合并操作时,实际上会运行两个
    Git diff
    命令:

    git diff --find-renames <merge-base> HEAD     # figure out what we did
    git diff --find-renames <merge-base> <other>  # figure out what they did
    
    这就是“我们改变了什么”:重命名操作

    $ git diff --find-renames branch-a^ branch-a
    diff --git a/myBarFile b/myBarFile
    new file mode 100644
    index 0000000..5716ca5
    --- /dev/null
    +++ b/myBarFile
    @@ -0,0 +1 @@
    +bar
    diff --git a/myFooFile b/myFooFile
    deleted file mode 100644
    index 257cc56..0000000
    --- a/myFooFile
    +++ /dev/null
    @@ -1 +0,0 @@
    -foo
    
    这就是“他们改变了什么”:删除一个文件,添加另一个

    Git现在负责将
    myFooFile
    重命名为
    myBarFile
    (内容为
    foo
    ),同时删除
    myFooFile
    ,同时创建内容为
    bar
    myBarFile

    它不可能同时做这两件事,所以我们会发生冲突。同时,它可以像我们做的那样进行重命名,因此它在工作树(仅限于)中这样做,留下
    myBarFile
    包含
    foo

    你想知道:

    如何正确地修复我们添加的cherry pick冲突并最终。。。使用包含bar的myBarFile

    Git所需要的只是在工作树中写入包含所需内容的
    myBarFile
    版本,然后调整索引,使其条目处于零阶段。目前,索引中的内容是:

    $ git ls-files --stage
    100644 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 2      myBarFile
    
    而且
    myBarFile
    包含您不想要的内容

    注意:我知道我可以在git冲突解决期间使用
    git签出分支-a--myBarFile

    是:从由
    branch-a
    标识的提交中提取
    myBarFile
    的版本,在第0阶段将其写入索引,在第2阶段删除条目,并使所有内容都准备好提交。(作为奖励,它还将文件写入工作树,以便您可以看到它,尽管Git此时实际上并不关心工作树的版本。)因此,这是一种快速实现所需结果的好方法。不过,我们可以研究另一种方法,这种方法在某些情况下可能很有用:

    [但是]我不认为这是一种愚蠢的方式

    Git没有(单一)方式。Git是一种工具。你喜欢怎么用就怎么用。如果您希望在不首先接触索引的情况下调整工作树内容,则可以使用
    git show
    提取文件的
    branch-a
    版本:

    $ git show branch-a:myBarFile > tmp
    $ cat tmp
    bar
    $ mv tmp myBarFile
    $ git add myBarFile
    
    如果我们检查实际暂存区域,我们会发现:

    $ git ls-files --stage
    100644 5716ca5987cbf97d6bb54920bea6adde242d87e6 0       myBarFile
    
    这正是我们想要的,所以我们现在可以
    git cherry pick--继续
    git commit
    完成这个cherry pick:

    $ git cherry-pick --continue
    
    此时,您首选的编辑器应该打开包含主题
    rm myFooFile add myBarFile
    和其他数据的消息文件(因为这是您选择的提交)。将其写出来会导致:

    [master 1837c17] rm myFooFile add myBarFile                   
     Date: Fri Jun 15 22:21:48 2018 -0700
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    git log--oneline
    显示您想要的:

    1837c17 (HEAD -> master) rm myFooFile add myBarFile
    a30b874 git mv myFooFile myBarFile
    bde7df5 First commit add myFooFile
    

    (注意:我的配置中有
    log.decoration=auto

    非常感谢您的详细回答,但我仍然不清楚。你说:“它不可能同时做这两件事,所以我们会产生冲突。同时它可以做我们做的重命名,所以它在工作树(仅)中做了,留下包含foo的myBarFile。”,在那之后,为什么Git不能尝试将
    bar
    添加到
    myBarFile
    中,然后在
    myBarFile
    中创建一个带尖括号的diff
    。还有为什么
    git show:3:myBarFile
    在冲突解决期间不起作用,我希望在其中看到
    bar
    1837c17 (HEAD -> master) rm myFooFile add myBarFile
    a30b874 git mv myFooFile myBarFile
    bde7df5 First commit add myFooFile