git rebase,跟踪'local'和'remote'

1zmg4dgp  于 12个月前  发布在  Git
关注(0)|答案(4)|浏览(179)

在做git rebase时,我经常很难弄清楚在解决冲突时“本地”和“远程”发生了什么。我有时有这样的印象,他们从一个提交到下一个提交交换立场。
这可能(肯定)是因为我仍然没有正确地理解范式。
当变基时,谁是“本地”,谁是“远程”?
(我使用P4Merge来解决冲突。

gr8qqesn

gr8qqesn1#

TL;DR;

总结(作为Benubird注解),当:

git checkout A
git rebase   B    # rebase A on top of B
  • localB(rebaseonto),
  • remoteA

以及:

git checkout A
git merge    B    # merge B into A
  • localA(合并),
  • remoteB

一个rebase切换ours(rebase开始前的当前分支)和theirs(要在其上进行rebase的分支)。
kutschkem指出,在GUI mergetool上下文中

*本地引用部分重基的提交:“ours”(上游分支)
*remote是指传入的更改:“theirs“-变基之前的当前分支。

见本答案最后一部分的插图。

rebase时的反转

这种混淆可能与在变基过程中ourstheirs的反转有关。
(相关摘录)
git rebase man page
请注意,一个rebase merge的工作原理是在<upstream>分支的顶部重放每个来自工作分支的提交。
因此,当合并冲突发生时:

  • 报道为“ours”的一侧是迄今为止的重定基系列,从<upstream>开始,
  • 而'theirs'是工作分支。换句话说,两侧是交换的。

反转图解

合并时

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

,我们不改变当前分支'B',所以我们拥有的仍然是我们正在做的(我们从另一个分支合并)

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

在变基时:

但是在一个rebase上,我们切换到另一边,因为rebase做的第一件事就是 checkout 上游分支!(在其上重放当前提交)

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

A**git rebase upstream**将首先将B的HEAD更改为上游分支HEAD(因此与先前的“当前”工作分支相比,“我们的”和“他们的”的交换机)。

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

,然后rebase将在新的'our' B分支上重放'their' commit:

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

注意:“上游”概念是数据的引用集(所有存储库,或者像这里一样,分支,可以是 * 本地 * 分支),从中读取数据或添加/创建新数据。

local”和“remote”与'mine'和'theirs'

Pandawood在评论中添加:
对我来说,问题仍然存在,谁是“本地”,谁是“远程”(因为在git中进行重新定基时不会使用术语“我们的”和“他们的”,提到它们似乎会使答案更加混乱)。

GUI git mergetool

kutschkem补充说,这是正确的:
在解决冲突时,git会说:

local: modified file and remote: modified file.

我很肯定这个问题的目的是在这一点上的本地和远程的定义。在这一点上,根据我的经验,我认为:

*本地引用部分重基的提交:“ours”(上游分支)
*remote是指传入的更改:“theirs“-变基之前的当前分支。
git mergetool确实提到了'local'和'remote'

Merging:
f.txt

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

例如,KDiff3display the merge resolution like so

meld则为display it too

VimDiffwhich displays也是如此:
使用git mergetool -t gvimdiff调用Vimdiff作为mergetool。最新版本的Git使用以下窗口布局调用Vimdiff:

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

*LOCAL

包含当前分支上文件内容的临时文件。

*BASE

一个临时文件,包含用于合并的公共基。

*REMOTE

包含要合并的文件内容的临时文件。

*MERGED

包含冲突标记的文件。
Git已经尽可能多地执行了自动冲突解决,并且该文件的状态是LOCALREMOTE的组合,并且在Git无法自行解决的任何内容周围都有冲突标记。
mergetool应将解析结果写入此文件。

sqserrrh

sqserrrh2#

底线
git rebase

  • LOCAL =您将转换为的基
  • REMOTE =你要移到顶部的提交
    git merge
  • LOCAL =要合并到的原始分支
  • REMOTE =另一个分支,你正在合并它的提交

换句话说,LOCAL总是原始的,而REMOTE总是那些提交之前不存在的家伙,因为它们正在被合并或重新基于顶部
证明给我看
当然可以。不要相信我的话!这里有一个简单的实验,你可以自己看看。
首先,确保正确配置了git mergetool。(如果你没有,你可能不会阅读这个问题无论如何。)然后找到一个目录工作。
设置存储库:

md LocalRemoteTest
cd LocalRemoteTest

创建初始提交(使用空文件):

git init
notepad file.txt  (use the text editor of your choice)
  (save the file as an empty file)
git add -A
git commit -m "Initial commit."

在不是master的分支上创建提交:

git checkout -b notmaster
notepad file.txt
  (add the text: notmaster)
  (save and exit)
git commit -a -m "Add notmaster text."

在master分支上创建一个提交:

git checkout master
notepad file.txt
  (add the text: master)
  (save and exit)
git commit -a -m "Add master text."

gitk --all

此时,您的存储库应该如下所示:

下面是rebase测试:

git checkout notmaster
git rebase master
  (you'll get a conflict message)
git mergetool
  LOCAL: master
  REMOTE: notmaster

现在是合并测试。关闭mergetool而不保存任何更改,然后取消变基:

git rebase --abort

然后又道:

git checkout master
git merge notmaster
git mergetool
  LOCAL: master
  REMOTE: notmaster
git reset --hard  (cancels the merge)

你的结果应该和上面显示的一样。

pgccezyw

pgccezyw3#

我也是,困惑了很长一段时间,经常做出错误的决定,不得不重新开始。
免责声明:我不是gitMaven,所以如果这里有任何错误,请纠正我!
我想我已经意识到,我的困惑是因为我描绘了一个变基不同于许多画它。下面是两个通常用于描述变基的图形:

--1--2--3--4--5
     \
      6--7--8

然后

--1--2--3--4--5--6--7--8

当然,这是绘制它的一种方法,但我对rebase发生的事情的感觉是这样的:

--1--2--3--4--5
                 \
                  6--7--8

这当然是完全相同的。但从“我们/他们”的Angular 来看,情况就不同了。在第二种情况下,感觉好像“我们”仍然“在”分支(“6--7--8”)上,我们想从“主”那里获得更改。所以在这个世界上“我们的”仍然是“分支”。这就是让我困惑的地方。
但是在第一个“世界视图”中,我认为这是Git的视图,我们移动到master(我们想要将 * 转换到 * 的提交),从那里我们依次选择分支上的每个提交并应用它们。所以“我们的”变成了“主”,最初是5。在6成功应用后,“我们的”是6,但实际上是“在”主机上的6'

--1--2--3--4--5--6'
     \
      6--7--8

然后我们继续用“7”来做同样的事情。
所以在merge中,你“在”8上,并将两者组合成一个新的提交,但在rebase中,你移动到5,并尝试将提交中的差异应用于分支上的新提交。
因此,变基的最终结果的“真实”画面应该是:

--1--2--3--4--5--6'--7'--8'
     \
      6--7--8

在重定基之后,你就在8'上了。你的分支也是如此(我想!)。(在我的脑海中)这可以想象为:

--1--2--3--4--5
     \           \
      6--7--8     6'--7'--8'
f45qwnt8

f45qwnt84#

我没有完全理解你的问题,但我认为下面的图表解决了你的问题。(Rebase:Remote Repository -> Workspace)

来源:My Git Workflow

相关问题