如何在 fork 和 master 分支之间获得 git 冲突
How do I get a git conflict between a fork and the master branch
我fork了一个项目,添加和修改了文件。
过了一会儿,我意识到我应该从 master 分支更新一些配置。我尝试 git-pull master 和其他东西,结果我丢失了一些文件(不知何故)。
现在我删除了整个目录(可能不是很聪明)并且我正在尝试从上次提交加载我的分支,如下所示:
> git clone [URL of the project]
> git checkout [code of the last commit in my fork]
> git pull origin master
它只说:
* branch master -> FETCH_HEAD
Already up-to-date.
什么都不做,也没有实施任何更改。我预计某些文件会发生一些冲突,所以我想知道如何到达两个版本(我的叉子和主版本)会显示冲突(通常与 >>>>>>>> HEAD .. .)
这里有一个基本问题:导致冲突的不是分支。或者,也许更好一点:分支是必要的,但还不够。 (但这也取决于我们如何定义branch。)
要在 Git 中发生冲突,您必须:
- 执行三路合并,使用
git merge
1
- 使用两个输入提交(这将来自分支,但这里重要的不是分支)
- 其提交图导致Git找到第三个合并基础提交,不同于其他两个输入,最后
- 两次提交都对同一文件的同一行进行了更改。2
在所有这些中,术语 fork 完全无关紧要。一个分支只是一个克隆,具有一些特殊的语义,由任何托管提供商提供给你一个点击网络界面 "fork" 按钮,或网络可访问 "fork" API。如果你分叉了一个存储库,你就克隆了它。如果你克隆了你的克隆体,你就再次克隆了它。重要的是你有哪些 commits,通过他们的哈希 ID——这是他们的真实名字——即使你通过分支名称 find 那些提交。
每次提交都会记住其直接父代的哈希 ID,3 这会导致一个向后指向的链:
... <-F <-G <-H
其中 H
代表一些提交哈希 ID。提交 H
记住其前身提交的哈希 ID。我们没有使用丑陋的大哈希 ID,而是使用另一个字母来代表它,所以我们称之为 G
。因此,提交 H
指向 (持有提交 G
的哈希 ID)。提交 G
依次指向 F
,它继续向后指向。
在您自己的存储库中制作了一个克隆,或者只是一堆提交——所有重要的是 提交——你现在有更多像这样的东西:
I--J <-- branch1
/
...--G--H
\
K--L <-- branch2
分支 names、branch1
和 branch2
在这里,保存 last 提交的哈希 ID在分支机构。 Git 自动更新它们,例如,当您在分支上使用 git checkout
并进行新的提交时,这样当您进行新的提交时,分支会增长并且名称继续指向最后一次提交。所以现在他们分别指向提交 J
和 L
。
如果您现在 运行 git checkout branch1
和 git merge branch2
,Git 将把提交 J
和 L
作为您的两个输入提供,并会自己找到最好的 shared 提交,在这种情况下显然是提交 H
,它在 both 分支机构。 Git 将:
- 将
H
中的所有文件与 J
中的所有文件进行比较——git diff --find-renames H J
——看看 你 改变了什么,并且
- 将
H
中的所有文件与 L
-git diff --find-renames H L
中的所有文件进行比较,看看 它们 发生了什么变化。
合并操作尝试合并这两组更改,将合并后的更改应用于 H
中的文件,以便创建一组可用于新快照中的文件合并提交。
如果合并成功,Git 将自己进行新的合并提交 M
:
I--J
/ \
...--G--H M <-- branch1 (HEAD)
\ /
K--L <-- branch2
HEAD
表示这是我们所在的分支,因为我们在 branch1
上,这就是 Git 更新以保存哈希 ID 的名称新提交 M
。提交 M
具有通过将组合更改应用于 H
中的快照而创建的快照。
如果存在合并冲突,Git 将停止而不进行 M
。 Git 留下一堆烂摊子让你清理。4 你必须自己进行合并,然后告诉 Git 你已经成功解决了所有冲突并产生了正确 合并结果。然后,您使用 git merge --continue
或 git commit
(其中之一)完成合并并提交 M
和 您 构建的快照。
1Git 也使用三向合并来实现 git cherry-pick
和 git revert
,以及其他一些特殊情况,所以你可以在不使用 git merge
的情况下获得合并冲突。但是 git merge
是通常的来源,也是您所描述的内容,因此您可以将其视为 "when you run git merge
" 而不会损失太多准确性。
注意 git pull
表示 运行 git fetch
,然后 运行 第二个 Git 命令,通常是 git merge
。所以 git pull
只是获取 + 合并。
2关于 "the same" 的含义有一些棘手的细节,对于可以重命名的文件和可能只是邻接而不是重叠的行.但是同样,您可以将其视为 "different change to same lines of same file" = "conflict" 并且足够接近。
3对于合并提交,提交会记住其父项的所有——通常只有两个——因此不仅指向提交合并时所在的分支,也提交合并时合并分支的尖端提交。
4乱七八糟的merge状态占用了index,这里我们完全没有描述。 Git 还让您尽最大努力合并工作树中文件中的冲突更改,并留下 关于 为 git merge --continue
记录的合并的信息,其中 运行s git commit
,或 git commit
,选择进行合并提交。
您可以使用 git merge --abort
退出所有内容,这会将所有内容恢复到开始 git merge
之前的状态。
我fork了一个项目,添加和修改了文件。
过了一会儿,我意识到我应该从 master 分支更新一些配置。我尝试 git-pull master 和其他东西,结果我丢失了一些文件(不知何故)。
现在我删除了整个目录(可能不是很聪明)并且我正在尝试从上次提交加载我的分支,如下所示:
> git clone [URL of the project]
> git checkout [code of the last commit in my fork]
> git pull origin master
它只说:
* branch master -> FETCH_HEAD
Already up-to-date.
什么都不做,也没有实施任何更改。我预计某些文件会发生一些冲突,所以我想知道如何到达两个版本(我的叉子和主版本)会显示冲突(通常与 >>>>>>>> HEAD .. .)
这里有一个基本问题:导致冲突的不是分支。或者,也许更好一点:分支是必要的,但还不够。 (但这也取决于我们如何定义branch。)
要在 Git 中发生冲突,您必须:
- 执行三路合并,使用
git merge
1 - 使用两个输入提交(这将来自分支,但这里重要的不是分支)
- 其提交图导致Git找到第三个合并基础提交,不同于其他两个输入,最后
- 两次提交都对同一文件的同一行进行了更改。2
在所有这些中,术语 fork 完全无关紧要。一个分支只是一个克隆,具有一些特殊的语义,由任何托管提供商提供给你一个点击网络界面 "fork" 按钮,或网络可访问 "fork" API。如果你分叉了一个存储库,你就克隆了它。如果你克隆了你的克隆体,你就再次克隆了它。重要的是你有哪些 commits,通过他们的哈希 ID——这是他们的真实名字——即使你通过分支名称 find 那些提交。
每次提交都会记住其直接父代的哈希 ID,3 这会导致一个向后指向的链:
... <-F <-G <-H
其中 H
代表一些提交哈希 ID。提交 H
记住其前身提交的哈希 ID。我们没有使用丑陋的大哈希 ID,而是使用另一个字母来代表它,所以我们称之为 G
。因此,提交 H
指向 (持有提交 G
的哈希 ID)。提交 G
依次指向 F
,它继续向后指向。
在您自己的存储库中制作了一个克隆,或者只是一堆提交——所有重要的是 提交——你现在有更多像这样的东西:
I--J <-- branch1
/
...--G--H
\
K--L <-- branch2
分支 names、branch1
和 branch2
在这里,保存 last 提交的哈希 ID在分支机构。 Git 自动更新它们,例如,当您在分支上使用 git checkout
并进行新的提交时,这样当您进行新的提交时,分支会增长并且名称继续指向最后一次提交。所以现在他们分别指向提交 J
和 L
。
如果您现在 运行 git checkout branch1
和 git merge branch2
,Git 将把提交 J
和 L
作为您的两个输入提供,并会自己找到最好的 shared 提交,在这种情况下显然是提交 H
,它在 both 分支机构。 Git 将:
- 将
H
中的所有文件与J
中的所有文件进行比较——git diff --find-renames H J
——看看 你 改变了什么,并且 - 将
H
中的所有文件与L
-git diff --find-renames H L
中的所有文件进行比较,看看 它们 发生了什么变化。
合并操作尝试合并这两组更改,将合并后的更改应用于 H
中的文件,以便创建一组可用于新快照中的文件合并提交。
如果合并成功,Git 将自己进行新的合并提交 M
:
I--J
/ \
...--G--H M <-- branch1 (HEAD)
\ /
K--L <-- branch2
HEAD
表示这是我们所在的分支,因为我们在 branch1
上,这就是 Git 更新以保存哈希 ID 的名称新提交 M
。提交 M
具有通过将组合更改应用于 H
中的快照而创建的快照。
如果存在合并冲突,Git 将停止而不进行 M
。 Git 留下一堆烂摊子让你清理。4 你必须自己进行合并,然后告诉 Git 你已经成功解决了所有冲突并产生了正确 合并结果。然后,您使用 git merge --continue
或 git commit
(其中之一)完成合并并提交 M
和 您 构建的快照。
1Git 也使用三向合并来实现 git cherry-pick
和 git revert
,以及其他一些特殊情况,所以你可以在不使用 git merge
的情况下获得合并冲突。但是 git merge
是通常的来源,也是您所描述的内容,因此您可以将其视为 "when you run git merge
" 而不会损失太多准确性。
注意 git pull
表示 运行 git fetch
,然后 运行 第二个 Git 命令,通常是 git merge
。所以 git pull
只是获取 + 合并。
2关于 "the same" 的含义有一些棘手的细节,对于可以重命名的文件和可能只是邻接而不是重叠的行.但是同样,您可以将其视为 "different change to same lines of same file" = "conflict" 并且足够接近。
3对于合并提交,提交会记住其父项的所有——通常只有两个——因此不仅指向提交合并时所在的分支,也提交合并时合并分支的尖端提交。
4乱七八糟的merge状态占用了index,这里我们完全没有描述。 Git 还让您尽最大努力合并工作树中文件中的冲突更改,并留下 关于 为 git merge --continue
记录的合并的信息,其中 运行s git commit
,或 git commit
,选择进行合并提交。
您可以使用 git merge --abort
退出所有内容,这会将所有内容恢复到开始 git merge
之前的状态。