如何将远程仓库分支添加到本地仓库
How to get remote repo branch added to local repo
newly created - by creating a folder & running the command git init
in short creating a local git repo from the top.
我这里有一个本地 git 存储库(新创建的),有 2 个分支 。现在这些分支只是我创建的虚拟分支,没有什么重要的。
$ git branch
* repo2-branch1
repo2-branch2
我这里还有一个来自 Github 的远程存储库 (private) 和一个分支 "TLA1",现在记住我上面提到的新创建的本地存储库和这两个分支?我想做的是 ADD 这个 "TLA1" 分支作为 repo2-branch1
& repo2-branch2
的分支之一正如我提到的,在我新创建的本地存储库中。
假设已添加 "TLA1" 分支。所以当我输入 git branch
时,我希望它是这样的。
$ git branch
* repo2-branch1
repo2-branch2
TLA1
当然,当我输入 git log
时,当我切换到 "TLA1" 时,我也会有远程存储库中的提交,如您在图片,因为对我来说这些提交非常重要。
我尝试过的解决方案:
我做了很多研究,发现 this,我认为这已经是它了,因为它与我的目标相似。但是当我尝试它时出现错误。
$ git checkout -b TLA1 origin/TLA1
fatal: 'origin/TLA1' is not a commit and a branch 'TLA1' cannot be created from it
我也没有尝试过这个,因为这可能会对我的远程仓库造成影响git reset --hard <remote>/<branch_name>
,而且这似乎不是我正在寻找的解决方案。
有什么解决办法吗?我真的很想在我新创建的存储库中有这个分支。
您需要告诉 Git 先跟踪远程存储库。所以你必须做
git remote add origin <url>
接下来你可以告诉git只从远程获取那个分支
git fetch origin TLA1
那你就可以切换到分支了
git checkout TLA1
将遥控器添加到您的本地存储库,然后从中获取。
git remote add REMOTE_NAME REMOTE_URL
git fetch REMOTE_NAME
git checkout -b branch_name REMOTE_NAME/branch_name
最后一个命令从远程引用创建一个本地分支。
然后 git 分支应该显示:
git branch
LOCAL1
LOCAL2
branch_name
TL;DR
您需要 运行 git fetch origin
才能 运行 git checkout TLA1
.
长
你走在正确的轨道上,但还有很多东西要知道——人们捡到的很多错误的东西你应该小心。
要忘记的事情
在熟练使用Git之前,您需要un-学习一些东西。这些虚假声明如下:
“分支很重要”:这没有错,但也不对。第一个问题是单词 branch,它在 Git 中根本就是模棱两可的。如果我们坚持使用 two-word 短语 分支名称 ,我们会得到更有用的东西。分支名称很重要,但仅对 人类 而言。 Git 使用它们来帮助我们找到 提交; 真正重要的是提交。
“远程分支”:这个 two-word 短语,如果有的话,比“分支”这个词本身更糟糕。人们用它来表示至少三种不同的事物。让我们也避免这个短语。 Git 文档使用术语 remote-tracking branch 或 remote-tracking branch name,它们是列出的名称通过 git branch -r
。这个短语还不错,但是里面的branch这个词毫无意义。我们就称它为 remote-tracking 名称.
需要学习的东西
Git 中重要的是 提交 。了解有关提交的这些事情:
每一个都有一个唯一的哈希ID。某个提交的哈希 ID 表示 that 提交。没有其他提交——任何地方,在 any Git 存储库中——将具有 that 哈希 ID。 That 提交——任何地方,在 any Git 存储库中——将具有 that 哈希 ID。
提交是在不同的 Git 克隆之间共享的内容。分支名称不是 共享的 。你的 Git 克隆有 你的 分支名称,而其他一些克隆有 its 分支名称。您可能 想要 使用相同的名称,以保持直截了当,但这取决于您(尽管 Git 会在这里提供帮助,因为这是很常见的事情)。
每个提交由两部分组成:
提交的主要数据是所有文件的快照。这些文件将永远冻结:它们以压缩的 read-only、Git-only 和 de-duplicated 形式存储。 de-duplication 处理这样一个事实,即大多数时候,大多数新提交大多包含与上一次提交相同的 文件。存储在提交中的文件被冻结,甚至不能被非 Git 的程序 读取 (更不用说写入)这一事实当然是一个问题.
提交的另一部分是它的元数据。这包括做出提交的人的姓名、他们的电子邮件地址以及 当 他们做出提交时的 date-and-time-stamp。所有这些东西也是 read-only。对于 Git 本身至关重要,Git 向此元数据添加一些 previous 提交或提交的哈希 ID。我们称这些为提交的 parents。
提交表单链;分支名称帮助我们(和Git)找到提交
鉴于我们有一些简单的提交序列:
... <-F <-G <-H
这里的每个字母代表一个实际的 Git 哈希 ID,我们最终得到一个线性提交链, 结束 与提交 H
.如果我们知道 H
的实际哈希 ID,我们可以让 Git 提取此提交(见下文)。或者,我们可以让 Git 读取 H
的元数据并向我们展示提交者是谁……或者使用它来查找 H
的 [=447= 的实际哈希 ID ] 提交 G
.
因为G
和H
都有快照,我们可以Git 比较这两个快照。所有匹配的文件都是无趣的,因为它们匹配。 不匹配的任何文件都更有趣,我们可以让Git弄清楚它们有什么不同并向我们展示区别。这样,我们就可以看到我们改变了什么。 Git 不会 存储 更改:它只存储快照。但是我们可以看到一个快照 as 变化,因为一个提交有一个 parent.
我们也可以让 Git 返回到 G
,并使用它来查找 F
,从而将 G
视为更改。从那里,我们可以回到 F
,并使用它来查找更早的提交,等等。但是要做到这一切,我们需要链中 last 提交的实际哈希 ID。这就是分支名称的来源:像 repo-branch1
这样的分支名称只是存储一些哈希 ID。根据定义,名称中存储的哈希 ID 是分支中的 last 提交。 Git 会在那里开始并向后工作。在之后是否有以后的提交并不重要:
...--E--F <-- br1
\
G--H <-- br2
此处 H
是 last 提交(例如在 F
和 G
之后)在 br2
中,而提交F
是 br1
中的 最后 提交。通过 F
的提交在 两个分支 中,但是 br1
starts-or-ends(取决于你如何看待它)在 F
和向后工作,而 br2
结束于 H
并向后工作。
提取的提交
因为提交是 read-only,我们实际上不能直接处理或使用它们。我们必须选择一些提交并将其设为 当前提交 。当我们这样做时,Git 提取 所有提交到工作区的文件,Git 调用 工作树 或 work-tree。这些是您可以查看和使用的文件。它们是普通的日常计算机文件,计算机上的每个程序都可以使用。但它们实际上并不是 in Git.
我们运行:
git checkout br2
(或 Git 2.23 或更高版本中的 git switch br2
)。 Git 使用名称 br2
来查找该分支的最后一次(或 提示)提交(注意歧义词,在这种情况下意味着一些提交结束于H
)。 Git 然后从该提交中提取文件,以便我们可以查看和使用它们,并使该提交成为 当前提交 同时使该分支名称成为 当前分支。我喜欢这样画:
...--E--F <-- br1
\
G--H <-- br2 (HEAD)
特殊名称 HEAD
附加到 分支名称。这就是“在分支上”的意思:名称 HEAD
定位分支名称 br2
。分支名称本身定位提交 H
,这是 Git 提取的提交。
如果我们进行 new 提交,Git 将打包快照,添加元数据,设置 parent 的新提交成为 current 提交 H
,并使用所有这些来写出新提交。这为提交分配了新的、丑陋的 random-looking——但实际上根本不是随机的——哈希 ID,我将其称为 I
。由于 I
的 parent 是 H
,因此 I
指向 H
。然后 Git 简单地将 I
的哈希 ID 写入当前 name, br2
, 给出:
...--E--F <-- br1
\
G--H--I <-- br2 (HEAD)
因此 分支名称 的特殊功能是它 在我们创建时自动移动以指向新的提交 。 Git 通过将名称 HEAD
附加到分支名称来完成此操作。
Git 有其他名称——例如标签名称和 remote-tracking 名称——也 指向提交(通过存储提交哈希 ID),但是您不能将 HEAD
附加到它们。
Remote-tracking 姓名和 git fetch
Remote-tracking 名称的形式类似于 origin/TLA1
:它们以 远程名称 开头,例如 origin
。远程名称就是你使用git remote add
时使用的名称; origin
只是第一个 标准 。如果您使用 git clone
到 运行 git init
和 git remote add
等等,git clone
将使用 origin
作为标准的第一个远程名称。 注意:您没有使用 git clone
,所以当您 运行 git remote add
.
时,名称将由您决定
如上所述,您不能将 HEAD
附加到 remote-tracking 名称。此外,您通常不会自己创建这些名称。您可以使用git branch -r
列出您现在拥有的那些,但是如果您不创建它们,您如何获得它们?
最后一个问题的答案是 git fetch
命令创建了它们。 fetch 命令非常复杂(原因有好有坏),我绝对不会在这里介绍太多,但我们可以相对简单地描述它,如下所示:git fetch
有你的 Git 调用上传一些其他 Git 并从中获取内容:
首先,您的 Git 让他们的 Git 列出所有分支名称、标签名称和其他类似名称。它们带有散列 ID——主要是提交散列 ID,尽管标签名称有时会变得有点复杂。
然后您的 Git 会选择这些名称和哈希 ID。你 Git 可以判断你是否有提交,因为每个 Git 使用 相同的 random-looking-but-not-random hash IDs 相同提交。所以你的 Git 立即知道你是否有 他们的 分支的提示提交。
如果您不这样做,您的 Git 会要求他们的 Git 进行提交。他们也提供提交的 parents,并且您的 Git 检查您是否有 那些 提交。通过这种 have/want 序列(通过一些重要的优化,避免每次都必须列出每个哈希 ID),您的 Git 计算出他们有什么提交,你没有,你会需要,并要求他们。
他们将所有这些提交打包并发送给您。这里的细节可以很多,但在通常情况下你会看到“计数”和“压缩”等等,然后你的 Git 收到一个充满提交和其他内部 Git objects 的包。然后,您的 Git 会将其全部保存在您的存储库中。
您现在拥有您之前拥有的所有提交,加上他们拥有但您没有拥有的任何提交(除非您的 Git 不想要它们,例如,single-branch 克隆)。
最后,您的 Git 现在 创建或更新您的 remote-tracking 名称 。对于他们拥有的每个 分支 名称,您的 Git 会为您的存储库创建或更新相应的 remote-tracking 名称。
这意味着您永远无法直接获得它们的分支名称。您获得他们的分支名称,然后 将它们 更改为您的 remote-tracking 名称。这作为您的 Git 对它们分支名称的 记忆 。这些由 git fetch
. 创建或更新,直到你 运行 git fetch
,你才会 拥有 origin/TLA1
.
结论
重要的是提交。分支名称和其他名称可以帮助您(和 Git)找到 提交。
您的 remote-tracking 名字来自 运行宁 git fetch
。您告诉 git fetch
调用哪个 远程 。您的 Git 调出那个遥控器并查看其分支并获取其提交,除非您已经拥有它们。然后您的 Git 根据需要更新或创建 remote-tracking 名称。 (旁注:你的 Git 不会 删除 一个“死”的名字,除非你告诉它,所以一旦他们删除了一些分支名称,你就会留下陈旧的 remote-tracking 个名字。)
您可以随时创建自己的分支名称,但要创建名称,您必须提交 才能point-to。所以你通常会想先得到他们最新的:git fetch
,然后第二个Git命令。
旁白:git pull
表示 运行 git fetch
,然后 运行 第二个 Git 命令 。因为它需要两个命令来做有用的事情,所以人们喜欢 git pull
,运行 是两个命令。我不喜欢 git pull
,因为我喜欢在这两个 之间插入命令 ,并且可能使用 git pull
为第二个命令提供的相对较少的选项集以外的其他选项, 但这取决于你。
newly created - by creating a folder & running the command
git init
in short creating a local git repo from the top.
我这里有一个本地 git 存储库(新创建的),有 2 个分支 。现在这些分支只是我创建的虚拟分支,没有什么重要的。
$ git branch
* repo2-branch1
repo2-branch2
我这里还有一个来自 Github 的远程存储库 (private) 和一个分支 "TLA1",现在记住我上面提到的新创建的本地存储库和这两个分支?我想做的是 ADD 这个 "TLA1" 分支作为 repo2-branch1
& repo2-branch2
的分支之一正如我提到的,在我新创建的本地存储库中。
假设已添加 "TLA1" 分支。所以当我输入 git branch
时,我希望它是这样的。
$ git branch
* repo2-branch1
repo2-branch2
TLA1
当然,当我输入 git log
时,当我切换到 "TLA1" 时,我也会有远程存储库中的提交,如您在图片,因为对我来说这些提交非常重要。
我尝试过的解决方案:
我做了很多研究,发现 this,我认为这已经是它了,因为它与我的目标相似。但是当我尝试它时出现错误。
$ git checkout -b TLA1 origin/TLA1
fatal: 'origin/TLA1' is not a commit and a branch 'TLA1' cannot be created from it
我也没有尝试过这个,因为这可能会对我的远程仓库造成影响git reset --hard <remote>/<branch_name>
,而且这似乎不是我正在寻找的解决方案。
有什么解决办法吗?我真的很想在我新创建的存储库中有这个分支。
您需要告诉 Git 先跟踪远程存储库。所以你必须做
git remote add origin <url>
接下来你可以告诉git只从远程获取那个分支
git fetch origin TLA1
那你就可以切换到分支了
git checkout TLA1
将遥控器添加到您的本地存储库,然后从中获取。
git remote add REMOTE_NAME REMOTE_URL
git fetch REMOTE_NAME
git checkout -b branch_name REMOTE_NAME/branch_name
最后一个命令从远程引用创建一个本地分支。
然后 git 分支应该显示:
git branch
LOCAL1
LOCAL2
branch_name
TL;DR
您需要 运行 git fetch origin
才能 运行 git checkout TLA1
.
长
你走在正确的轨道上,但还有很多东西要知道——人们捡到的很多错误的东西你应该小心。
要忘记的事情
在熟练使用Git之前,您需要un-学习一些东西。这些虚假声明如下:
“分支很重要”:这没有错,但也不对。第一个问题是单词 branch,它在 Git 中根本就是模棱两可的。如果我们坚持使用 two-word 短语 分支名称 ,我们会得到更有用的东西。分支名称很重要,但仅对 人类 而言。 Git 使用它们来帮助我们找到 提交; 真正重要的是提交。
“远程分支”:这个 two-word 短语,如果有的话,比“分支”这个词本身更糟糕。人们用它来表示至少三种不同的事物。让我们也避免这个短语。 Git 文档使用术语 remote-tracking branch 或 remote-tracking branch name,它们是列出的名称通过
git branch -r
。这个短语还不错,但是里面的branch这个词毫无意义。我们就称它为 remote-tracking 名称.
需要学习的东西
Git 中重要的是 提交 。了解有关提交的这些事情:
每一个都有一个唯一的哈希ID。某个提交的哈希 ID 表示 that 提交。没有其他提交——任何地方,在 any Git 存储库中——将具有 that 哈希 ID。 That 提交——任何地方,在 any Git 存储库中——将具有 that 哈希 ID。
提交是在不同的 Git 克隆之间共享的内容。分支名称不是 共享的 。你的 Git 克隆有 你的 分支名称,而其他一些克隆有 its 分支名称。您可能 想要 使用相同的名称,以保持直截了当,但这取决于您(尽管 Git 会在这里提供帮助,因为这是很常见的事情)。
每个提交由两部分组成:
提交的主要数据是所有文件的快照。这些文件将永远冻结:它们以压缩的 read-only、Git-only 和 de-duplicated 形式存储。 de-duplication 处理这样一个事实,即大多数时候,大多数新提交大多包含与上一次提交相同的 文件。存储在提交中的文件被冻结,甚至不能被非 Git 的程序 读取 (更不用说写入)这一事实当然是一个问题.
提交的另一部分是它的元数据。这包括做出提交的人的姓名、他们的电子邮件地址以及 当 他们做出提交时的 date-and-time-stamp。所有这些东西也是 read-only。对于 Git 本身至关重要,Git 向此元数据添加一些 previous 提交或提交的哈希 ID。我们称这些为提交的 parents。
提交表单链;分支名称帮助我们(和Git)找到提交
鉴于我们有一些简单的提交序列:
... <-F <-G <-H
这里的每个字母代表一个实际的 Git 哈希 ID,我们最终得到一个线性提交链, 结束 与提交 H
.如果我们知道 H
的实际哈希 ID,我们可以让 Git 提取此提交(见下文)。或者,我们可以让 Git 读取 H
的元数据并向我们展示提交者是谁……或者使用它来查找 H
的 [=447= 的实际哈希 ID ] 提交 G
.
因为G
和H
都有快照,我们可以Git 比较这两个快照。所有匹配的文件都是无趣的,因为它们匹配。 不匹配的任何文件都更有趣,我们可以让Git弄清楚它们有什么不同并向我们展示区别。这样,我们就可以看到我们改变了什么。 Git 不会 存储 更改:它只存储快照。但是我们可以看到一个快照 as 变化,因为一个提交有一个 parent.
我们也可以让 Git 返回到 G
,并使用它来查找 F
,从而将 G
视为更改。从那里,我们可以回到 F
,并使用它来查找更早的提交,等等。但是要做到这一切,我们需要链中 last 提交的实际哈希 ID。这就是分支名称的来源:像 repo-branch1
这样的分支名称只是存储一些哈希 ID。根据定义,名称中存储的哈希 ID 是分支中的 last 提交。 Git 会在那里开始并向后工作。在之后是否有以后的提交并不重要:
...--E--F <-- br1
\
G--H <-- br2
此处 H
是 last 提交(例如在 F
和 G
之后)在 br2
中,而提交F
是 br1
中的 最后 提交。通过 F
的提交在 两个分支 中,但是 br1
starts-or-ends(取决于你如何看待它)在 F
和向后工作,而 br2
结束于 H
并向后工作。
提取的提交
因为提交是 read-only,我们实际上不能直接处理或使用它们。我们必须选择一些提交并将其设为 当前提交 。当我们这样做时,Git 提取 所有提交到工作区的文件,Git 调用 工作树 或 work-tree。这些是您可以查看和使用的文件。它们是普通的日常计算机文件,计算机上的每个程序都可以使用。但它们实际上并不是 in Git.
我们运行:
git checkout br2
(或 Git 2.23 或更高版本中的 git switch br2
)。 Git 使用名称 br2
来查找该分支的最后一次(或 提示)提交(注意歧义词,在这种情况下意味着一些提交结束于H
)。 Git 然后从该提交中提取文件,以便我们可以查看和使用它们,并使该提交成为 当前提交 同时使该分支名称成为 当前分支。我喜欢这样画:
...--E--F <-- br1
\
G--H <-- br2 (HEAD)
特殊名称 HEAD
附加到 分支名称。这就是“在分支上”的意思:名称 HEAD
定位分支名称 br2
。分支名称本身定位提交 H
,这是 Git 提取的提交。
如果我们进行 new 提交,Git 将打包快照,添加元数据,设置 parent 的新提交成为 current 提交 H
,并使用所有这些来写出新提交。这为提交分配了新的、丑陋的 random-looking——但实际上根本不是随机的——哈希 ID,我将其称为 I
。由于 I
的 parent 是 H
,因此 I
指向 H
。然后 Git 简单地将 I
的哈希 ID 写入当前 name, br2
, 给出:
...--E--F <-- br1
\
G--H--I <-- br2 (HEAD)
因此 分支名称 的特殊功能是它 在我们创建时自动移动以指向新的提交 。 Git 通过将名称 HEAD
附加到分支名称来完成此操作。
Git 有其他名称——例如标签名称和 remote-tracking 名称——也 指向提交(通过存储提交哈希 ID),但是您不能将 HEAD
附加到它们。
Remote-tracking 姓名和 git fetch
Remote-tracking 名称的形式类似于 origin/TLA1
:它们以 远程名称 开头,例如 origin
。远程名称就是你使用git remote add
时使用的名称; origin
只是第一个 标准 。如果您使用 git clone
到 运行 git init
和 git remote add
等等,git clone
将使用 origin
作为标准的第一个远程名称。 注意:您没有使用 git clone
,所以当您 运行 git remote add
.
如上所述,您不能将 HEAD
附加到 remote-tracking 名称。此外,您通常不会自己创建这些名称。您可以使用git branch -r
列出您现在拥有的那些,但是如果您不创建它们,您如何获得它们?
最后一个问题的答案是 git fetch
命令创建了它们。 fetch 命令非常复杂(原因有好有坏),我绝对不会在这里介绍太多,但我们可以相对简单地描述它,如下所示:git fetch
有你的 Git 调用上传一些其他 Git 并从中获取内容:
首先,您的 Git 让他们的 Git 列出所有分支名称、标签名称和其他类似名称。它们带有散列 ID——主要是提交散列 ID,尽管标签名称有时会变得有点复杂。
然后您的 Git 会选择这些名称和哈希 ID。你 Git 可以判断你是否有提交,因为每个 Git 使用 相同的 random-looking-but-not-random hash IDs 相同提交。所以你的 Git 立即知道你是否有 他们的 分支的提示提交。
如果您不这样做,您的 Git 会要求他们的 Git 进行提交。他们也提供提交的 parents,并且您的 Git 检查您是否有 那些 提交。通过这种 have/want 序列(通过一些重要的优化,避免每次都必须列出每个哈希 ID),您的 Git 计算出他们有什么提交,你没有,你会需要,并要求他们。
他们将所有这些提交打包并发送给您。这里的细节可以很多,但在通常情况下你会看到“计数”和“压缩”等等,然后你的 Git 收到一个充满提交和其他内部 Git objects 的包。然后,您的 Git 会将其全部保存在您的存储库中。
您现在拥有您之前拥有的所有提交,加上他们拥有但您没有拥有的任何提交(除非您的 Git 不想要它们,例如,single-branch 克隆)。
最后,您的 Git 现在 创建或更新您的 remote-tracking 名称 。对于他们拥有的每个 分支 名称,您的 Git 会为您的存储库创建或更新相应的 remote-tracking 名称。
这意味着您永远无法直接获得它们的分支名称。您获得他们的分支名称,然后 将它们 更改为您的 remote-tracking 名称。这作为您的 Git 对它们分支名称的 记忆 。这些由 git fetch
. 创建或更新,直到你 运行 git fetch
,你才会 拥有 origin/TLA1
.
结论
重要的是提交。分支名称和其他名称可以帮助您(和 Git)找到 提交。
您的 remote-tracking 名字来自 运行宁 git fetch
。您告诉 git fetch
调用哪个 远程 。您的 Git 调出那个遥控器并查看其分支并获取其提交,除非您已经拥有它们。然后您的 Git 根据需要更新或创建 remote-tracking 名称。 (旁注:你的 Git 不会 删除 一个“死”的名字,除非你告诉它,所以一旦他们删除了一些分支名称,你就会留下陈旧的 remote-tracking 个名字。)
您可以随时创建自己的分支名称,但要创建名称,您必须提交 才能point-to。所以你通常会想先得到他们最新的:git fetch
,然后第二个Git命令。
旁白:git pull
表示 运行 git fetch
,然后 运行 第二个 Git 命令 。因为它需要两个命令来做有用的事情,所以人们喜欢 git pull
,运行 是两个命令。我不喜欢 git pull
,因为我喜欢在这两个 之间插入命令 ,并且可能使用 git pull
为第二个命令提供的相对较少的选项集以外的其他选项, 但这取决于你。