如何创建GIT远程跟踪分支机构 [英] How to create git Remote-Tracking Branch

查看:18
本文介绍了如何创建GIT远程跟踪分支机构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

They said就这么简单

您可以告诉Git跟踪新创建的远程分支,只需使用-u标志和"git推送"即可。

但这对我来说从来都不管用。

如何创建GIT远程跟踪分支,

Git现在可以通知您"未推送"和"未拉出"提交。

这是我的:

$ git status 
On branch newfeature/v4-json
nothing to commit, working tree clean

与我预期的相比,引用above article

$ git status
# On branch dev
# Your branch and 'origin/dev' have diverged,
# and have 1 and 2 different commits each, respectively.
#
nothing to commit (working directory clean)

即未推送和未拉出提交的信息。
即,我希望看到与以下相同的内容:

$ git status
On branch master
Your branch is ahead of 'origin/master' by 3 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

然而,从我上面的实际输出中,您可以看到我不能再看到到目前为止我已经提交了多少次,尽管我已经提交了几次

我是这样做的:

$ git push -u origin newfeature/v4-json
Counting objects: 12, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (12/12), 1.87 KiB | 958.00 KiB/s, done.
Total 12 (delta 9), reused 0 (delta 0)
remote: Resolving deltas: 100% (9/9), completed with 9 local objects.
remote: 
remote: Create a pull request for 'newfeature/v4-json' on GitHub by visiting:
remote:      https://github.com/.../pull/new/newfeature/v4-json
remote: 
To github.com:xxx/yyy.git
 * [new branch]      newfeature/v4-json -> newfeature/v4-json
Branch 'newfeature/v4-json' set up to track remote branch 'newfeature/v4-json' from 'origin' by rebasing.

但我没有git设置的来自‘Origin’的远程跟踪分支‘newFeature/v4-json’:

A)git remote show origin根本没有显示我的新功能的远程跟踪分支:

$ git remote show origin
* remote origin
  Fetch URL: git@github.com:go-easygen/easygen.git
  Push  URL: git@github.com:go-easygen/easygen.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branches configured for 'git pull':
    master             rebases onto remote master
    newfeature/v4-json rebases onto remote newfeature/v4-json
  Local refs configured for 'git push':
    master             pushes to master             (up to date)
    newfeature/v4-json pushes to newfeature/v4-json (up to date)

根据http://www.gitguys.com/topics/adding-and-removing-remote-branches

,以下是我想看到的
$ git remote show origin
* remote origin
  Fetch URL: /tmp/.../git/rp0
  Push  URL: /tmp/.../git/rp0
  HEAD branch: master
  Remote branches:
    master     tracked
    newfeature tracked
  Local branches configured for 'git pull':
    master     rebases onto remote master
    newfeature rebases onto remote newfeature
  Local refs configured for 'git push':
    master     pushes to master     (up to date)
    newfeature pushes to newfeature (up to date)
注意:在Remote branches:部分中,除了master tracked,还有一个newfeature tracked。根据上面的文章,这个newfeature tracked称为远程跟踪分支

B)也不是git branch -a

$ git branch -a
  master
* newfeature/v4-json
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

只有一个remotes/origin/master远程跟踪名称,而我希望有更多。例如(无关紧要,但仅用于显示包含更多远程跟踪名称的大小写),

$ git branch -a
* master
  remotes/origin/HEAD
  remotes/origin/master
  remotes/origin/v1.0-stable
  remotes/origin/experimental

C)也不是git branch -vv

$ git branch -vv
  master             75369c3 [origin/master] - [*] allow ...
* newfeature/v4-json 8c98d9c - [*] update ...

我期待看到的是

$ git branch -vv
  master             75369c3 [origin/master] - [*] allow ...
* newfeature/v4-json 8c98d9c [origin/newfeature/v4-json] - [*] update ...

此外,

git pull没有更新远程本地分支:

$ git pull
From github.com:xxx/yyy
 * branch            newfeature/v4-json -> FETCH_HEAD
Already up to date.
Current branch newfeature/v4-json is up to date.

$ git pull
From github.com:xxx/yyy
 * branch            newfeature/v4-json -> FETCH_HEAD
Already up to date.
Current branch newfeature/v4-json is up to date.

$ git pull
From github.com:xxx/yyy
 * branch            newfeature/v4-json -> FETCH_HEAD
Already up to date.
Current branch newfeature/v4-json is up to date.

也就是说,无论我拉多少次,我都得不到相同的输出

$ git pull
Already up to date.
Current branch master is up to date.

以上均为正常。我已经用MS VS创建了很多次远程跟踪分支,结果完全符合我的预期,而不是上面的结果。然而,我不喜欢黑魔法,所以我想知道如何使用普通的git来做同样的事情。

那么创建Git远程跟踪分支的正确方式是什么?

推荐答案

已更新地址编辑(git branch -agit branch -vv)输出:是,缺少某些。目前还不完全清楚哪里出了问题,但我有一个猜测。git push -u输出的这一部分:

 * [new branch]      newfeature/v4-json -> newfeature/v4-json
Branch 'newfeature/v4-json' set up to track remote branch 'newfeature/v4-json' from 'origin' by rebasing.

显示Git将origin/newfeature/v4-json(分为两部分)设置为newfeature/v4-json的上游。但是您的git branch -agit branch -vv输出显示origin/newfeature/v4-json不存在。

我可以通过创建单分支克隆来复制此行为的一个关键元素。使用git clone --depth=numbergit clone --single-branch将生成这样的克隆。这样做的副作用是,您的Git永远不会为以外的任何分支创建任何远程跟踪名称,是您告诉Git您所关心的那个分支。如果的问题,则修复方法是将克隆转换为普通(多分支)克隆。(如果您使用--depth创建单分支方面,取消浅克隆可能也是明智的做法。)

查看origin的克隆是否设置为单分支:

$ git config --get-all remote.origin.fetch

在普通克隆中,将打印以下内容:

+refs/heads/*:refs/remotes/origin/*

在选择了分支master的单分支克隆中,将打印以下内容:

+refs/heads/master:refs/remotes/origin/master

这告诉您的Git:master创建远程跟踪名称,而不是为*创建远程跟踪名称,即所有分支

撤消origin的克隆的单分支:

$ git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'

(或直接编辑.git/config,例如git config --edit,这是我的首选方法)。另请参阅How do I "undo" a --single-branch clone?

要将浅克隆转换为完整(非浅)克隆,只需运行:

$ git fetch --unshallow
请注意,此操作独立于单分支,尽管git clone默认情况下将它们绑定在一起(您可以在git clone时间用git clone --depth=number --no-single-branch覆盖它)。在2.15之前的Git版本中没有针对浅表的命令行测试;在2.15或更高版本中,使用:

git rev-parse --is-shallow-repository

但在此之前,您必须测试文件是否存在.git/shallow

if [ -f $(git rev-parse --git-dir)/shallow ]; then
    echo true
else
    echo false
fi

模拟git rev-parse --is-shallow-repository

顺便说一句,您希望查看的输出有问题。您说您希望看到newfeature作为遥控器上的一个分支,但不能,因为名称newfeature/v4-json需要存在,这排除了newfeature存在的能力。

(原始答案在行下方)


$ git push -u origin newfeature/v4-json

这完全按照您的要求工作。在您显示的其余输出中,一切都很正常。因此,不清楚您认为是什么错误;实际上没有任何错误。我将解决您显示的另一条消息:

# Your branch and 'origin/dev' have diverged,
# and have 1 and 2 different commits each, respectively.

下面。

这一切意味着什么?(长)

回顾Git的工作原理和Git的一些非常特殊的术语可能会有所帮助。特别是,您使用的短语-远程跟踪分支-在我看来是一个糟糕的术语,具有明显的误导性。它一个Git术语,所以我们应该理解人们使用它是什么意思,但它是一个糟糕的术语,意思是人滥用它,如果你被某人的用法搞糊涂了,可能值得退一步,重新考虑这些事情。

首先,让我们注意到Git实际上是关于提交的。提交是Git的raison d'être;没有提交,我们根本不会使用Git。那么让我们来看看什么是提交。

每次提交都包含文件,但不仅仅是一组文件。它是您拍摄快照时所有文件的快照,1,但它也有一些元数据:有关存储数据的信息。最明显的是您在git log输出中看到的内容:您的姓名和电子邮件地址,计算机对您提交时的日期和时间的概念,以及您为提交而保存的原因,即您的日志消息。这些都是供您或其他人在未来使用的:某天、可能明天、可能几个月或几年后,您可能会回顾您刚刚做出的承诺,并问问自己:我到底为什么要答案应该在您的日志消息中。

因为提交将文件存储为快照,在时间上冻结,不变,并且永远存在(或只要提交本身存在),所以它们非常适合存档。以后的任何时候,您都可以回到过去,查看您当时保存的内容。你不能改变它:它是过去的,固定的,冻结在时间里的。即使Git也无法更改它,我们稍后将看到这一点。

为了查找提交,Git需要一个名称。这些名称是而不是分支机构名称!或者,更准确地说,您可以开始使用分支名称,但Git不需要这个名称。任何提交的真实名称都是其散列ID。每个提交的散列ID看起来是随机的,但实际上,它是提交的整个内容的加密校验和,对提交中的每一位数据都非常敏感:所有冻结的快照,以及您的姓名、时间戳和日志消息。这就是您或任何人不能更改提交的原因:更改任何内容都会更改散列ID,然后您得到的是一个新的、不同的提交。在提交之前,没有人知道提交的散列ID是什么。此时,它将获得一个唯一的ID。没有人会将该ID用于任何其他提交!而且没有人可以更改Commit中的任何内容:Git将知道您是否尝试,因为ID不再匹配。2

这个拼图游戏的最后一两个关键部分。首先,在每个提交中,Git将前一个提交的散列ID(真实名称)存储为元数据的一部分。也就是说,Git不仅保存您的姓名和时间等,还保存您用来进行这个新提交的提交的原始散列ID。Git将这个保存的散列ID称为提交的。这意味着每个提交都指向它的父级提交,在一个向后的链中。

例如,假设我们在存储库中只有两个提交ABA是第一个提交,所以它故意没有父级--这是一个特例。但B来自A,因此B指向A

A <-B

如果提取提交B,执行一些工作,然后重新提交C,则新提交会自动指向B

A <-B <-C

意味着Git只需要知道最后提交的明显随机的散列ID。在本例中,提交C。如果它的实际散列ID是cba9876...或其他什么,Git可以使用它来查找C内容。这些内容包括COMMITB的实际散列ID。然后,Git可以使用它来查找B,其内容包括COMMITA的实际散列ID。Git可以使用它查找A,而A没有父级,所以现在,最终,Git可以停止向后工作。

这个由分支名称标识的分支提示提交类似C的过程在Git中至关重要。这就是历史存在的方式。Git存储库中的历史记录提交,通过这些向后箭头连接。你从尽头开始,沿着历史一步一步地走,看看你可以沿着父箭头到达哪里。

分支机构名称和其他类似名称出现时,最后一块拼图进入画面。让我们暂停一下,完成这里的脚注,然后深入到分支机构名称和图表绘制。


1Git实际上是从索引中创建快照,但我们在此不会深入讨论这些细节,而是要说明所拍摄的快照--针对该提交而在时间上永久冻结的--是当时在索引中的内容,这至少可能与您在工作树中看到的内容不同。

2Git实际上会在看起来方便或合适的时候检查这一点。自动检测Git存储库的意外损坏,例如,你试图在Dropbox中存储--Dropbox有时会在你(和Git)背后修改文件,Git会抓住它。不幸的是,很少有修复损坏的存储库的好方法--相反,Git倾向于依赖这样一种想法,即Git存储库可以在各地复制。你可能在其他地方有一份很好的复制品,所以你就把这一份完全扔掉。


分支名称查找提交散列ID

任何现有的存储库-嗯,除了一个完全空的、新鲜的、新的存储库,其中还没有提交--都有一些提交集。这些提交形成了我们刚才看到的回溯链,例如:

A <-B <-C

我们和Git需要某种方法来记录此链中最后一个提交的哈希ID。

Git实现这一点的方法是使用Git所称的引用引用。裁判的形式有很多种,但最重要的三种是:

  • 分支机构名称,如master
  • 远程跟踪名称,如origin/master。(Git将这些远程跟踪分支机构名称称为远程跟踪分支机构名称,我认为这不是一个好名字;我已改用远程跟踪分支机构名称,我认为这样更难出错。)
  • 标记名,如v1.3
它们实际上都是由相同的底层技术实现的,但我们在这里只是将它们视为不同形式的名称。分支名称具有特殊属性;所有其他名称没有此属性。

这些名称之一中包含的内容非常简单:它只是Git对象的实际原始散列ID,通常是提交。3因此,master这样的分支名称指向分支中的最后提交C在此图中:

A--B--C   <-- master

请注意,连接彼此提交的箭头出自子对象并指向(不可变的)父对象,这为我们提供了这种向后遍历方法。我们不必费心把他们吸引进来。但是,分支名称中的箭头会更改

当我们将提交添加到master时,Git会自动更新master的名称以保存新提交的哈希ID。因此,如果我们现在创建新提交,新提交D将指向回C

A--B--C   <-- master
       
        D

但Git将立即调整master,使其不指向C,而指向D

A--B--C--D   <-- master

由于D指向C,我们仍然可以找到所有提交:我们从末尾开始,像往常一样向后工作。C现在是此进程中的第二个提交,而不是第一个。


3分支名称必须包含提交对象散列ID,而标记名称更灵活。我们不需要在这里关心这件事。因为远程跟踪名称的值是从分支机构名称复制的,所以远程跟踪名称也只包含提交哈希ID。


分支机构名称是每个存储库的专用名称,但存储库之间相互通信

Git是分布式版本控制系统。这意味着每个Git存储库都是一个独立的孤岛,它需要的所有东西都位于该存储库的本地。如果有多个分支和多个提交,则它们都在一个存储库中:

A--B--C--D--G--H   <-- master
          
           E--F   <-- dev

为了让Git真正有用,我们经常使用Git与其他Git用户交换工作。为此,我们交换提交。它们的散列ID在所有Git Everywhere中是通用的,这是因为加密的校验和技巧。给定快照和元数据,每个Git Everywhere将计算相同的哈希ID。因此,如果我的存储库有AH这样的提交-请记住,这些单个大写字母代表唯一的、难看的大散列ID-我连接到您的存储库和有提交H,您的存储库也必须具有与我相同的提交。

如果您没有有提交H,我有一个您没有的提交。如果您有一些提交IJ有一个没有的提交。无论哪种方式,我们的Git都可以交换散列ID来查看谁拥有什么。发送提交的人将发送它们,接收提交的人将接收它们,发送者将向接收者提供所需的任何提交。

假设您正在接受我的新承诺。我有新的提交IJ,并且我的新提交J有一个名称,它记住了它的散列ID。在我的存储库中,我有以下内容:

A--B--C--D--G--H   <-- master
          
           E
            
             I--J   <-- dev

出于任何原因,我没有您在dev上提交的F。相反,我在dev上提交了I-J,在(共享)提交之后E

这是远程跟踪名称的用武之地

您的Git接受我的提交IJ。我的提交I具有父级E。因此您的存储库现在具有以下内容:

A--B--C--D--G--H   <-- master
          
           E--F   <-- dev
            
             I--J   <-- ???

您的Git存储库将使用什么名称来记住我的提交I?最好不要使用dev:如果您Git使dev指向CommitI,您将如何再次找到Commit?请记住,它有一个明显随机的哈希ID。您永远无法猜到它。

因此,您的Git所做的就是使用远程跟踪名称来记住我的分支。您的Git执行此操作:

A--B--C--D--G--H   <-- master, origin/master
          
           E--F   <-- dev
            
             I--J   <-- origin/dev

(假设我的master指向提交H)。

您的存储库中的origin/masterorigin/dev是(您的)远程跟踪名称,记住我的master和我的dev4此外,假设您现在查询Git,让它比较从dev到达的提交集与来自origin/dev的提交集,并使用Git使用的向后遍历方法。

dev开始,您将访问的提交是F,然后是E,然后是D,依此类推回到A。从origin/dev开始,您将访问的提交是J,然后是I,然后是E,然后是D,依此类推回到A哪些提交是哪条路径所特有的?dev中有多少个提交是您无法从origin/dev达到的,反之亦然?

将它们计算出来,然后与Git告诉您的进行比较:

# Your branch and 'origin/dev' have diverged,
# and have 1 and 2 different commits each, respectively.

我们的拼图游戏实际上遗漏了另一块拼图,我们将在最后一节讨论下面的git push时稍微描述一下。


4Git有时将这称为跟踪而不是记住,但这是Git严重过度使用单词的另一个方面。我在短语远程跟踪中使用过它,但至少在这里它是用连字符连接的,并将该词用作形容词来修饰远程


git pushgit fetch

不同

上面的过程是特定于git fetch的,其中Git从origin上的分支机构名称创建远程跟踪名称。当您让Git在origin调用Git并将他们的承诺提交给时,就会发生这种情况。

当然,您可以让Git在origin发送提交时调用他们的Git。这是git push操作,它非常类似。你的Git告诉他们的Git关于你有的承诺,他们没有。让我们画一些。我们将从以下内容开始:

A--B--C--D--G--H   <-- master, origin/master
          
           E--F   <-- dev
            
             I--J   <-- origin/dev

现在我们将运行git checkout mastergit checkout -b newfeature/v4-json,或者更简单的:

git checkout -b newfeature/v4-json master

我们现在拥有:

A--B--C--D--G--H   <-- master, origin/master, newfeature/v4-json (HEAD)
          
           E--F   <-- dev
            
             I--J   <-- origin/dev

我们已将特殊名称HEAD附加到newfeature/v4-json以记住哪个分支名称在我们添加新提交时更新。

现在,我们将创建一个新的提交。它可以不止一个,甚至,但为了说明起见,我们只创建一个。新的提交获得了一些又大又难看的散列ID,但我们在这里仅将其命名为K

                 K   <-- newfeature/v4-json (HEAD)
                /
A--B--C--D--G--H   <-- master, origin/master
          
           E--F   <-- dev
            
             I--J   <-- origin/dev

现在我们将让您的Git在origin调用Git,使用:

git push -u origin newfeature/v4-json

您的Git调出他们的Git并宣布您已提交KH5他们没有K,但他们确实有H,因此他们让您的Git通过提交K发送其快照和元数据。您的Git可以看出,因为他们有H,所以他们也有GD以及之前的所有内容,所以您只需将K及其内容发送给他们。

然后,在结尾处,您的Git会问他们:现在,如果可以,请将您的姓名newfeature/v4-json设置为指向提交K请注意,您没有设置xpt/newfeature/v4-json或类似的设置。您让他们设置他们的分支!他们实际上还没有anewfeature/v4-json,所以他们设置一个是很好的。他们就是这么做的!他们现在的存储库中有一个newfeature/v4-json,指向提交K

您的Git现在创建
您的远程跟踪名称
origin/newfeature/v4-json,指向提交K,以记住他们的newfeature/v4-json,指向提交K6但这只是意味着图形中有一个额外的名称,如下所示:

                 K   <-- newfeature/v4-json (HEAD), origin/newfeature/v4-json
                /
A--B--C--D--G--H   <-- master, origin/master
          
           E--F   <-- dev
            
             I--J   <-- origin/dev

由于-u选项,您的Git也会立即运行:

git branch --set-upstream-to=origin/newfeature/v4-json newfeature/v4-json

这将为您的分支newfeature/v4-json设置上游设置。您的每个分支都可以有一个一个(1)上游设置,通常就是这样使用的。有关详细信息,请参阅Why do I need to do `--set-upstream` all the time?


5您的Git可以告诉他们F,但只有当您在此处说git push origin dev时才会这样做。使用git push origin newfeature/v4-json,无论是否使用-u,根据需要告诉您的Git:告诉他们关于提交的KHGDCB和/或A您的其他未共享提交是故意保密的。

6记住,由于散列ID的魔力,K提交在每个GitEverywhere中是通用的。每个Git要么按其哈希IDK,然后提交;要么根本没有K,因此无关紧要。

(这不一定是100%保证的。假设K的散列ID实际上是b5101f929789889c2e536d915698f58d5c5c6b7a。这是Git存储库中Git本身提交的散列ID。如果您从未将您的Git存储库连接到用于Git的Git存储库,则您和他们使用相同的散列ID进行不同提交是正常的。但是,如果您确实曾经将您的Git存储库连接到用于Git的Git存储库,则会发生一些不太好的事情。简而言之,你没有得到Git的提交,他们也没有得到你的提交:这两个存储库目前根本不能组合。对于您和维护Git的人来说,这可能是完全没有问题的。但也请参阅How does the newly found SHA-1 collision affect Git?)

这篇关于如何创建GIT远程跟踪分支机构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆