简体   繁体   English

Git克隆一个已经是克隆的存储库

[英]Git cloning a repository that is already a clone

对已经是另一个远程存储库克隆的存储库进行git clone是否有任何不良副作用?

There's no side effects but you should understand exactly what happens when you clone a repository.没有副作用,但您应该确切了解克隆存储库时会发生什么。

Some theory一些理论

The "problem" is that when you clone a repository "the normal way"—that is, without any funky knobs adjusted when calling git clone —you do not end up with a repository which is the same as the source one. “问题”在于,当您以“正常方式”克隆存储库时——也就是说,在调用git clone时没有调整任何时髦的旋钮——您最终不会得到与源代码相同的存储库。 It indeed contains exactly the same history but it has different branch layout.它确实包含完全相同的历史记录,但具有不同的分支布局。

To explain it in a non-scientific way, let's take an example:为了以非科学的方式解释它,让我们举个例子:

  1. A source repo contains branches "master", "dev" and "release".源代码库包含分支“master”、“dev”和“release”。

    It also contains two tags, "v1" and "v2".它还包含两个标签,“v1”和“v2”。

    The "HEAD" reference in that repository points to a branch "master".该存储库中的“HEAD”引用指向分支“master”。

  2. When you clone this repo, your local clone will have:当您克隆此 repo 时,您的本地克隆将具有:

    • The three remote-tracking branches: "origin/master", "origin/dev" and "origin/release".三个远程跟踪分支:“origin/master”、“origin/dev”和“origin/release”。

    • The two tags, "v1" and "v2".两个标签,“v1”和“v2”。

    • A local branch named "master" which points to the same commit the remote-tracking branch "origin/master" does.一个名为“master”的本地分支指向与远程跟踪分支“origin/master”相同的提交。

  3. If you now clone this clone the result will have:如果你现在克隆这个克隆,结果将是:

    • A single remote-tracking branch "origin/master".单个远程跟踪分支“origin/master”。

    • A single local branch "master".单个本地分支“master”。

    • The two tags, "v1" and "v2".两个标签,“v1”和“v2”。

This might appear weird, but in fact this is explicitly stated in the manual page:这可能看起来很奇怪,但实际上手册页中明确说明了这一点:

Clones a repository into a newly created directory, creates remote-tracking branches for each branch in the cloned repository (visible using git branch -r ), and creates and checks out an initial branch that is forked from the cloned repository's currently active branch.将存储库克隆到新创建的目录中,为克隆存储库中的每个分支创建远程跟踪分支(使用git branch -r可见),并创建并检出从克隆存储库当前活动分支分叉的初始分支。

After the clone, a plain git fetch without arguments will update all the remote-tracking branches, and a git pull without arguments will in addition merge the remote master branch into the current master branch, if any (this is untrue when "--single-branch" is given; see below).克隆之后,不带参数的普通 git fetch 将更新所有远程跟踪分支,并且不带参数的 git pull 还会将远程 master 分支合并到当前 master 分支(如果有的话)(当“--single”时这是不正确的) -branch”给出;见下文)。

This default configuration is achieved by creating references to the remote branch heads under refs/remotes/origin and by initializing remote.origin.url and remote.origin.fetch configuration variables.这个默认配置是通过在refs/remotes/origin下创建对远程分支头的引用并通过初始化remote.origin.urlremote.origin.fetch配置变量来实现的。

So "clone" in git clone means that all the history is cloned (unless told otherwise) but the layout of branches is different.所以git clone “clone”意味着所有的历史都被克隆了(除非另有说明)但分支的布局是不同的。

The reasoning is this: exactly because Git is a distributed VCS, all branches in your non-bare repository are "yours" in the sense that you do work on them and only you decide how they get synchronized with the branches in other repostories, when and why.理由是这样的:正是因为Git 是一个分布式 VCS,所以您的非裸存储库中的所有分支都是“您的”,因为您确实在处理它们,并且只有您决定它们如何与其他存储库中的分支同步,当为什么。

So when you clone a repo "the normal way" Git:因此,当您以“正常方式”克隆一个仓库时,Git:

  • Only fetches the branches local to that repo: no remote-tracking branches are consdered.仅获取该存储库的本地分支:不考虑远程跟踪分支。

    This is because the remote-tracking branches serve as bookmarks to the states of other repositories, and no work is done on them.这是因为远程跟踪分支用作其他存储库状态的书签,并且没有对它们进行任何工作。

    To understand why Git behaves this way, consider that when you clone a Joe's repository most of the time you want Joe's work, not the stuff he fetched from whatever random repositories he communicated with.要理解为什么 Git 会这样,请考虑一下,当您克隆 Joe 的存储库时,大多数时候您想要的是 Joe 的工作,而不是他从与之通信的任何随机存储库中获取的内容。

  • Turns all the fetched branches into remote-tracking branches in the resulting repo.将所有获取的分支转换为生成的 repo 中的远程跟踪分支。

  • Creates a single local branch and checks it out.创建一个本地分支并检查它。

    This is merely a convenience which only adds to a possible confusion.这只是一种便利,只会增加可能的混淆。

What to do该怎么办

Well, git clone accepts a "--mirror" command-line option which produces a true copy of the origin repo but the resulting repo will be bare.好吧, git clone接受“--mirror”命令行选项,该选项会生成原始存储库的真实副本,但生成的存储库将是空的。 Should you re-clone the resulting repo again using the "--mirror" command-line option, you will again get the true copy.如果您再次使用“--mirror”命令行选项重新克隆生成的存储库,您将再次获得真正的副本。

If you did a "normal" clone (which, I reckon, you did) you still are able to get everything from that repository but git clone won't cut it: you'll need to do git init followed by git remote add origin <url> followed by a specially crafted git fetch .如果你做了一个“正常”的克隆(我认为你做到了),你仍然可以从那个存储库中获取所有东西,但git clone不会削减它:你需要先执行git init然后执行git remote add origin <url>后跟一个特制的git fetch

Exactly how to craft that git fetch , depends on what you really want to grab from the source repo, and where to put it.确切地说,如何制作git fetch取决于您真正想从源代码库中获取什么以及将它放在哪里。 For a start, consider that the source repo now has "origin/master" and "master", and they might very well contain diverged histories.首先,请考虑源存储库现在具有“origin/master”和“master”,它们很可能包含不同的历史记录。

Also note that cloning a non-bare repo using git clone --mirror will work but the result will not be very sensible as in this case git clone will dutifully copy all the branches—both local and remote-tracking—from the source repo verbatim, and remote-tracking branches in not something you typically expect to be present in a bare repo.另请注意,使用git clone --mirror克隆非裸git clone --mirror将起作用,但结果将不是很明智,因为在这种情况下git clone将尽职尽责地从源仓库逐字复制所有分支(本地和远程跟踪) ,和远程跟踪分支不是您通常希望出现在裸仓库中的东西。

如果最初没有检出它们,您肯定会错过初始存储库的分支。

No side effects.无副作用。 You can safely clone a repository that comes as result of git clone operation.您可以安全地克隆作为git clone操作结果的存储库。 By the way, this is where git differs from centralized systems like Subversion: the cloned repository is an exact copy of the original one (except from the branches that need to be checkeout manually).顺便说一下,这就是 git 与像 Subversion 这样的集中式系统不同的地方:克隆的存储库是原始存储库的精确副本(除了需要手动检出的分支)。

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

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