git rebase,跟踪“本地"和“远程" [英] git rebase, keeping track of 'local' and 'remote'

查看:46
本文介绍了git rebase,跟踪“本地"和“远程"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在执行 git rebase 时,我经常很难弄清楚在解决冲突时本地"和远程"发生了什么.有时我的印象是他们从一次提交到下一次交换双方.

这可能(肯定)是因为我还没有正确理解.

rebase 时,谁是本地",谁是远程"?

(我使用 P4Merge 来解决冲突)

解决方案

TL;DR;

总结(作为 会 相同,显示:

<块引用>

使用 git mergetool -t gvimdiff 调用 Vimdiff 作为合并工具.最新版本的 Git 使用以下窗口布局调用 Vimdiff:

+--------------------------------+|本地 |基地 |远程 |+--------------------------------+|合并 |+--------------------------------+

<块引用>

  • 本地:
    包含当前分支上文件内容的临时文件.
  • BASE:
    包含合并公共基础的临时文件.
  • 远程:
    包含要合并的文件内容的临时文件.
  • 已合并:
    包含冲突标记的文件.

Git 已执行尽可能多的自动冲突解决,并且此文件的状态是 LOCALREMOTE 的组合,并带有围绕 Git 无法实现的任何内容的冲突标记自行解决.
mergetool 应将解析结果写入此文件.

When doing a git rebase, I often have difficulty working out what is happening with the 'local' and 'remote' when resolving conflicts. I sometimes have the impression that they swap sides from one commit to the next.

This is probably (definitely) because I still haven't properly understood.

When rebasing, who is 'local' and who is 'remote'?

(I use P4Merge for resolving conflicts)

解决方案

TL;DR;

To summarize (As Benubird comments), when:

git checkout A
git rebase   B    # rebase A on top of B

  • local is B (rebase onto),
  • remote is A

And:

git checkout A
git merge    B    # merge B into A

  • local is A (merge into),
  • remote is B

A rebase switches ours (current branch before rebase starts) and theirs (the branch on top of which you want to rebase).


kutschkem points out that, in a GUI mergetool context:

  • local references the partially rebased commits: "ours" (the upstream branch)
  • remote refers to the incoming changes: "theirs" - the current branch before the rebase.

See illustrations in the last part of this answer.


Inversion when rebase

The confusion might be related to the inversion of ours and theirs during a rebase.
(relevant extracts)

git rebase man page:

Note that a rebase merge works by replaying each commit from the working branch on top of the <upstream> branch.

Because of this, when a merge conflict happens:

  • the side reported as 'ours' is the so-far rebased series, starting with <upstream>,
  • and 'theirs' is the working branch. In other words, the sides are swapped.

Inversion illustrated

On a merge

x--x--x--x--x(*) <- current branch B ('*'=HEAD)
    
     
      --y--y--y <- other branch to merge

, we don't change the current branch 'B', so what we have is still what we were working on (and we merge from another branch)

x--x--x--x--x---------o(*)  MERGE, still on branch B
           ^        /
          ours     /
                  /
       --y--y--y--/  
               ^
              their


On a rebase:

But on a rebase, we switch side because the first thing a rebase does is to checkout the upstream branch! (to replay the current commits on top of it)

x--x--x--x--x(*) <- current branch B
    
     
      --y--y--y <- upstream branch

A git rebase upstream will first change HEAD of B to the upstream branch HEAD (hence the switch of 'ours' and 'theirs' compared to the previous "current" working branch.)

x--x--x--x--x <- former "current" branch, new "theirs"
    
     
      --y--y--y(*) <- upstream branch with B reset on it,  
                       new "ours", to replay x's on it

, and then the rebase will replay 'their' commits on the new 'our' B branch:

x--x..x..x..x <- old "theirs" commits, now "ghosts", available through reflogs
    
     
      --y--y--y--x'--x'--x'(*) <-  branch B with HEAD updated ("ours")
               ^
               |
        upstream branch


Note: the "upstream" notion is the referential set of data (a all repo or, like here, a branch, which can be a local branch) from which data are read or to which new data are added/created.


'local' and 'remote' vs. 'mine' and 'theirs'

Pandawood adds in the comments:

For me, the question still remains, which is "local" and who is "remote" (since the terms "ours" and "theirs" are not used when rebasing in git, referring to them just seems to make an answer more confusing).

GUI git mergetool

kutschkem adds, and rightly so:

When resolving conflicts, git will say something like:

local: modified file and remote: modified file. 

I am quite sure the question aims at the definition of local and remote at this point. At that point, it seems to me from my experience that:

  • local references the partially rebased commits: "ours" (the upstream branch)
  • remote refers to the incoming changes: "theirs" - the current branch before the rebase.

git mergetool does indeed mention 'local' and 'remote':

Merging:
f.txt

Normal merge conflict for 'f.txt':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (kdiff3):

For instance, KDiff3 would display the merge resolution like so:

And meld would display it too:

Same for VimDiff, which displays:

Invoke Vimdiff as a mergetool with git mergetool -t gvimdiff. Recent versions of Git invoke Vimdiff with the following window layout:

+--------------------------------+
| LOCAL  |     BASE     | REMOTE |
+--------------------------------+
|             MERGED             |
+--------------------------------+

  • LOCAL:
    A temporary file containing the contents of the file on the current branch.
  • BASE:
    A temporary file containing the common base for the merge.
  • REMOTE:
    A temporary file containing the contents of the file to be merged.
  • MERGED:
    The file containing the conflict markers.

Git has performed as much automatic conflict resolution as possible and the state of this file is a combination of both LOCAL and REMOTE with conflict markers surrounding anything that Git could not resolve itself.
The mergetool should write the result of the resolution to this file.

这篇关于git rebase,跟踪“本地"和“远程"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆