繁体   English   中英

Git通过主要内容推动新分支

[英]Git pushes new branch with master content

我通过以下方式将回购从Mercury迁移到git:

git init gitrepo
cd gitrepo
hg_fastexport -r <../hgclone>

(我希望我不会忘记任何事情),然后我在GitLab中创建了一个存储库,并在gitrepo(hg-fastexport将源导出到的地方)中创建了分支并将其推入

git checkout -b v4.1
git push origin refs/heads/v4.1:refs/heads/v4.1

当它使用2个分支时,它也出现在Gitab中,最后一个分支始终获取master分支的内容,而不是v4.1分支。

目前尚不清楚您的实际问题是什么 ,所以我将为您解决:

Git如何在两个不同的分支中具有相同的提交? (Mercurial不能。)

原因是在Mercurial中,提交没有独立于其分支的存在,而分支完全由其提交组成。 也就是说,每个提交恰好属于一个分支 分支名称是一个实体,表示“其记录的分支为此实体的每个提交”。

相反,在Git中,提交独立于分支 提交存在或不存在,仅是因为它存在或不存在。 提交不会记录包含该分支的分支(如果有)。 分支名称只是一(1)个哈希ID的别名,并且它可以作为别名的哪个哈希ID可以随时更改。

在两个VCS中,每个提交都记录其父提交ID:如果该提交是普通的非合并提交,则为一个ID;如果提交是一个,则至少两个(在Git中为两个或多个,在Mercurial中为两个)。合并提交。 这意味着在任一VCS中,如果给了我们某些特定的提交,我们可以检查该提交并找到其父级(或合并)。 然后,我们可以检查父级并找到其父级,依此类推。

如果对Mercurial称为heads的所有内容执行此操作,则会在Mercurial存储库中找到所有提交。 提交在有向无环图或DAG中充当顶点(或节点); 连接这些节点的弧是父ID。 我们发现以这种方式进行的每个提交都恰好在一个分支上,并且每个提交都记录它所在的(单个)分支。

相比之下,在Git中,我们真的不知道从哪里开始。 我们可以穷举枚举整个存储库以找到所有对象(Git在其存储库数据库中具有四种类型的对象),挑选出所有提交对象,然后从此处形成DAG。 但是,这些提交没有分支标识:我们不知道提交在哪个分支上! 而且,这种详尽的枚举需要很长时间-甚至在大型存储库中也要花费数分钟-因此我们几乎不用理会。

相反,我们采用了一种完全不同的方法:我们从存储在一个分支名称(例如master的哈希ID开始。 使用该一个分支名称,我们发现一个提交。 根据定义,该提交在master 然后,我们使用存储在该提交中的哈希ID找到该提交的父对象。 根据定义,这些提交也位于master 我们重复此过程,直到通过DAG跟踪了所有可到达的父弧,然后确定了master名称可以到达的每个提交,并且所有这些提交都在master

但是可能还有更多的分支名称。 因此,我们从另一个名称开始,例如v4.1 该名称包含一个哈希ID,用于查找提交。 根据定义,该提交在v4.1 然后,我们像以前一样找到该提交的父对象。 根据定义,这些提交也位于v4.1 我们重复此过程,直到通过DAG跟踪了所有可到达的父弧,然后从名称v4.1确定了所有可到达的提交,并且所有这些提交都在v4.1

请注意,在大多数提交DAG中,通常会有一个初始提交,所有其他提交都从该初始提交中扣除。 在Mercurial中,这一提交位于一个分支上,可能是一个名为default分支。 在Git中,此提交在每个分支上

因此, Git提交和Mercurial提交之间的根本区别在于,Git提交同时在许多分支上。 直到我们看到,这个特殊的提交要么是,或不是, 到达从一个具体的承诺,在尖端包含任何给定的Git提交组支路是动态确定的,通过咨询分公司及以下所有的人通过DAG分支。 如果可以这种方式到达,则它在该分支上; 如果不是,则不是。

这样的结果是分支创建是不同的

在Git和Mercurial中,要创建一个新分支,您都告诉VCS“创建一个新分支”,但是除了在一个新的空存储库中之外立即执行的操作非常不同。 1

在Git中,要存在一个分支名称 ,该名称必须标识一个特定的commit Git将此称为分支的尖端 ,我们说分支名称指向该特定提交。 但是在一个新的空存储库中, 没有commit ,因此没有分支名称可以存在!

Mercurial有一个类似的问题:分支包含该分支中的所有提交。 在一个新的空存储库中,没有提交,因此没有分支!

尽管如此,Git和Mercurial都具有当前分支的概念。 当前分支是将在其上进行提交的分支。 这允许两个VCS将当前分支名称记录为实际上尚不存在的分支。 完成此操作后,创建新的提交具有创建分支的副作用。 两个VCS都针对新的完全空的存储库执行此操作:第一次提交将创建当前分支(通常为defaultmaster )。

在Mercurial中,这都是非常简单和自动的:您创建一个新的提交; 它的分支是记录的“当前分支”是什么; 如果那是第一次在分支xyzzy上创建提交,那么现在在xyzzy上至少有一个提交,因此xyzzy存在。

但是,当Git会创建一个新的分支xyzzy一些现有的提交和分支机构,Git会简单地创建xyzzy立即指向当前提交。 假设您之前是master ,并且刚刚创建了xyzzy 名称xyzzymaster现在都指向同一个承诺:现在一切都在提交master两个master xyzzy

简而言之,这在Git中是完全正常的。 在分支v1.4上创建新提交将使该新提交在分支v1.4 ,至少直到发生其他情况使其他分支也包含该提交为止。 在分支上创建新提交时,告诉Git将分支提示设置为指向新创建的提交。 新创建的提交的父ID将是前一个提示(因为这是您已签出的提示),因此分支现在包含之前包含的每个提交,以及刚刚提交的新提交。


1您可以使用git checkout --orphan使Git的行为更像Mercurial,但如果执行此操作,则您进行的下一个提交将创建一个新的提交-一个没有父项的新提交,并在其中创建单独的子图提交DAG。 这几乎从来不是您想要的:在Git中,您希望提交同时在多个分支上。 总是希望这种“孤立分支”行为是在一个新的空存储库中创建第一次提交。

git checkout -b v4.1

-b告诉git从您当时所在的任何分支(可能是master创建一个新分支,然后切换到该分支,这意味着分支v4.1将指向与源分支完全相同的提交(再次,可能是master

看来您忘了在推送之前提交更改

分支v4.1仅具有在提交后所做的更改。

我发现了我犯的错误。 也许问题不是很清楚,但是当我创建一个新分支时,该分支将始终具有母版的内容。 它不包含分支。 这样做的原因是,我从汞迁移到git后,忘记了检查HEAD。 似乎那时我在母版或分支上工作,但是当我忘记签出(新迁移的HEAD)时,新分支和母版的内容保持不变。

我将在此处提供一张收据,该收据可导致建立正确的存储库。

克隆Mercurial目录:

  • 汞克隆http://mercurial.com ./hgclone

初始化git目录:

  • git init git-dir
  • cd git-dir

  • 将mercurial迁移到git: hg-fast-export -r ../hgclone

  • git checkout HEAD
  • 添加git仓库: git remote add origin $ remoterepo
  • 添加当前目录: git add。
  • 提交: git commit -m“初始提交”
  • push: git push -u原始主机

列出要创建的分支并将其更新到远程git目录-git branch

检出并将分支添加到远程git目录:

  • git checkout 分支
  • git添加
  • git push origin refs / heads / 分支 :refs / heads / branch

这是对我有用的基本步骤,用于将Merurial存储库导出到git并通过正确的分支将其存储到远程git存储库。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM