Git为不可恢复的灾难开出处方?

Git为不可恢复的灾难开出处方?,git,git-merge,git-fork,git-merge-conflict,Git,Git Merge,Git Fork,Git Merge Conflict,使用GIT似乎就像在玩一种没有人真正知道规则的新形式的国际象棋。这就是我所做的,请让我知道为什么这么快就出了问题 我有一个主分叉/回购和我的个人分叉 git clone https://github.com/myfork/project.git cd project git submodule update git checkout -b newbranch git remote add upstream https://github.com/CompanyX/project.git git f

使用GIT似乎就像在玩一种没有人真正知道规则的新形式的国际象棋。这就是我所做的,请让我知道为什么这么快就出了问题

我有一个主分叉/回购和我的个人分叉

git clone https://github.com/myfork/project.git
cd project
git submodule update
git checkout -b newbranch
git remote add upstream https://github.com/CompanyX/project.git
git fetch upstream  # <- hoping to update my fork
git pull upstream mainbranch # want the latest stuff from upstream
# Result: 100's of modified files, deleted files, and even merge conflicts... unrecoverable.
git克隆https://github.com/myfork/project.git
cd项目
git子模块更新
git checkout-b newbranch
git远程添加上游https://github.com/CompanyX/project.git
git-fetch上游#TL;博士
我想你想要的,作为罐装食谱,这里是:

git clone https://github.com/myfork/project.git
cd project
git remote add upstream https://github.com/CompanyX/project.git
git fetch upstream
git push --force origin upstream/master:master
但最后一个命令非常可疑。即使它是正确的,你也需要做更多。要确定您真正应该使用哪个命令,您需要了解更多。所以来吧

长的 我做错什么了吗

可能是……)当然,因为你没有得到你想要的结果。请确保开始。为了有效地使用这些工具,你需要知道/学习很多东西。有很多Git教程,还有几本书,但很多都不是很好。一个免费的,相当不错,而且不会太过时。但Git在不断发展:Git正式发布五年后的2010年的好文档在今天是糟糕的文档

在Git中,学习或可能忘记的最重要的事情之一就是一个分支到底是什么,它不是什么。如果您使用过其他版本控制系统(或源代码管理系统或您喜欢的任何短语),您可能对分支的工作方式有很多期望。Git无法满足大多数期望。其他VCSE通常确信分支,或者更准确地说,分支名称,是版本控制的全部。Git认为分支名称大多只是装饰性的绒毛

另一个需要处理的重要问题是Git是真正分布式的。许多VCSE都是集中式的:只有一个真正的存储库,而且它所说的就是这样。如果你有一份拷贝,那么,你的拷贝只是一份拷贝。他们决定了现实,你只需要服从他们。吉特不同意。每个存储库都是它自己的域之王。你的主人和他的主人、她的主人以及其他所有的主人一样好,甚至比他们都好。(当然,她的Git认为她的主人比你的主人好。)中央主人?没有这样的东西,那只是另一个Git存储库和另一个主存储库

在任何情况下,术语分支在Git中实际上都是不明确的。有时我们意味着一件事,有时我们意味着另一件事。我喜欢准确地说分支名称,特别是像
master
这样的文本字符串。一般来说,当有人说一个分支时,你必须找出它们是指一个分支名称,还是指一系列的提交,以散列ID为uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,例如一个远程跟踪名称,如
原点/master
(见下文)

如果叉子不是某物的复制品,那么它到底是什么?fork是git中另一个名称错误的术语吗

Git,我的意思是Git程序套件没有分叉。分叉不是Git概念。这是GitHub和Bitbucket等web托管服务在Git的基础上增加的功能。不过,什么是叉子这个问题还是个好问题。问题是要得到准确的答案,你必须说出你使用的是哪个网站。在本例中,它是
github.com
,因此我们可以使用github的定义定义fork。(不过,比特桶的情况非常相似。)

在GitHub上,fork是一个克隆,具有两个附加属性:

  • 在一个典型的克隆中,首先没有分支,然后Git立即添加一个分支。在GitHub fork克隆中,从N个分支开始,其中N是要克隆的存储库中存在的分支数

  • 在典型的克隆中,Git会创建一些远程跟踪名称。例如,如果今天进行克隆,将获得五个远程跟踪名称。1如果使用默认值,这五个远程跟踪名称将命名为
    origin/maint
    origin/master
    origin/next
    origin/pu
    ,以及
    origin/todo
    。在GitHub fork中,这些不存在,它们被替换为分支名称。例如,如果您分叉该存储库,您将得到分支名称
    maint
    master
    next
    pu
    ,和
    todo
    :相同的五个名称,但没有
    来源/
    。这五个名称将是分支名称,而不是远程跟踪名称

  • 最后,也是最重要的一点,GitHub将记住,您的fork是从任何存储库克隆的。这使GitHub能够为您提供GitHub提供的一系列功能:GitHub的东西,他们称之为pull请求,GitHub在“问题”页面上创建问题的能力,等等。这些都不是真正的Git。它们是作为一种附加值存在的,让你想使用GitHub,并且(GitHub的所有者希望至少如此)最终会向GitHub支付大笔资金。:-)


1我省略了您将看到的第六个名称-
origin/HEAD
,因为它是一个符号引用,这使得它与常规远程跟踪名称略有不同。这个
origin/HEAD
是针对Git特性的,在我看来,它没有实际的用处,因此可以忽略


一些特定的Git命令 此时,您已经从GitHub上的Git存储库中复制了一个克隆—您机器上的Git存储库。根据名称
myfork/project.git
,GitHub上的git存储库本身可能是另一个git存储库的副本。你现在在这个克隆中

不过,
git clone
有一点特别奇怪。It c
git clone https://github.com/myfork/project.git
cd project
mkdir project
cd project
git init
git remote add origin https://github.com/myfork/project.git
git fetch
git checkout <some-branch-name>
git checkout master
git submodule update
git checkout -b newbranch
git remote add upstream https://github.com/CompanyX/project.git
git fetch upstream  # <- hoping to update my fork
git pull upstream mainbranch
... <-F <-G <-H ...
...--F--G--H   <-- master
...--F--G--H--I   <-- master
          I--J   <-- master
         /
...--G--H
         \
          I--J   <-- master
         /
...--G--H
         \
          K--L   <-- whatever
          I--J
         /    \
...--G--H      M   <-- master
         \    /
          K--L   <-- whatever
          I--J   <-- master
         /
...--G--H
         \
          K--L   <-- origin/master
          I--J
         /    \
...--G--H      M   <-- master
         \    /
          K--L   <-- origin/master
          I--J
         /    \
...--G--H      M   <-- master, origin/master
         \    /
          K--L
          I--J   <-- master, origin/master
         /
...--G--H
         \
          K--L   <-- upstream/master
git push --force origin upstream/master:master
          I--J   <-- master
         /
...--G--H
         \
          K--L   <-- origin/master, upstream/master