繁体   English   中英

如何创建git Remote-Tracking分支

[英]How to create git Remote-Tracking Branch

他们说这很简单

您可以简单地通过将-u标志与“ git push”一起使用来告诉Git跟踪新创建的远程分支。

但这对我没有用。

如何创建git Remote-Tracking分支

Git现在可以通知您有关“未推动”和“未推动”的提交。

这是我的:

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

与我的期望相比,引用以上文章

$ 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根本不显示我的newfeature的远程跟踪分支:

$ 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外,还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多次创建了Remote-Tracking Branch,其结果完全符合我的预期,而不是上面的预期。 但是,我不喜欢黑魔术,所以我想知道如何使用纯git来做同样的事情。

那么创建git Remote-Tracking Branch的正确方法是什么?

编辑以更新地址( 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 ,这是我的首选方法)。 另请参阅如何“撤消”-单分支克隆?

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

$ git fetch --unshallow

请注意,尽管git clone默认将它们git clone --depth= number --no-single-branch在一起,但此操作与单分支无关(您可以在git clone时使用git clone --depth= number --no-single-branch覆盖此操作)。 在2.15之前的版本中,没有针对浅薄度的命令行测试; 在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实际上就是关于commit的全部内容。 承诺是Git的存在理由 没有提交,我们根本不会使用Git。 因此,让我们看看什么是提交。

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

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

为了找到提交,Git需要一个名称。 这些名称不是分支名称! 或者,更准确地说,您可以使用分支名称开始,但这不是Git所需的名称。 相反,任何提交的真实名称是其哈希ID 每个提交的哈希值ID 似乎是随机的,但实际上,它是上提交的全部内容的加密校验,以提交数据的每一个位极其敏感:所有冻结的快照,并您的姓名和时间-stamp和您的日志消息。 这就是为什么您或任何人都不能更改提交的原因:更改任何内容都会更改哈希ID,然后您将拥有一个新的不同的提交。 在进行提交之前,没人知道哈希ID是什么。 当时,它获得了唯一的ID。 没有人会将该ID用于其他任何提交! 没有人可以改变什么提交:Git会知道,如果你尝试,因为该ID不匹配了。 2

这个特殊的拼图游戏有最后一两个关键部分。 第一个是,在每个提交中,Git都将前一次提交的哈希ID(真实名称)存储为该元数据的一部分。 也就是说,Git不会只是保存您的姓名和时间等,同时也节省了您的使用使这个新提交的提交的原始哈希ID。 Git将此保存的哈希ID称为提交的父级 这意味着每个提交都在向后看的链中指向其父提交。

例如,假设我们在存储库中只有两个提交AB A是第一个提交,因此特意没有父提交-这是特例。 但是B是由A制成A ,因此B指向A

A <-B

如果您提取提交B ,执行一些工作,然后进行新的提交C ,则新的提交将自动指向B

A <-B <-C

意味着Git只需要知道最后一次提交的表面上随机的哈希ID。 在这种情况下,提交C 如果其实际的哈希ID是cba9876...或其他值,Git可以使用它来查找C内容 这些内容包括提交B的实际哈希ID。 然后,Git可以使用它来查找B ,其内容包括提交A的实际哈希ID。 Git可以使用它来查找A ,而A没有父母,所以现在,Git终于可以停止向后工作。

分支提示提交(例如,由分支名称标识的C向后工作的过程在Git中至关重要。 历史就是这样存在的 Git存储库中的历史记录提交,这些提交通过这些向后的箭头连接。 您从头开始,一次走动一次,遍历历史,按照父箭头查看可以到达的位置。

分支名称和其他此类名称显示出来时,这是最后一个拼图碎片输入图片的地方。 让我们暂停一下,在这里结束脚注,然后深入研究分支名称和图形绘制。


1 Git实际上是从索引制作快照的,但是我们不会在这里介绍这些细节,除了说要快照的内容(对于该提交,永远冻结的时间)就是当时索引中的内容,这至少可能与您在工作树中看到的内容有所不同。

2 Git实际上会在方便或适当的时候进行检查。 这会自动检测到Git存储库的意外损坏,例如在您尝试将其存储在Dropbox中时发生的情况。Dropbox有时会四处修改(和Git的)背后的文件,而Git会抓住它。 不幸的是,很少有修复损坏的存储库的好方法-而是,Git倾向于依赖Git存储库在各处复制的想法。 您可能在其他地方有一份不错的副本,因此您完全可以将其扔掉。


分支名称查找提交哈希ID

任何现有的存储库(好吧,除了一个完全空的,新鲜的, 没有提交的新存储库之外的任何其他存储库)都具有一组提交。 这些提交构成了我们刚刚看到的向后看的链,例如:

A <-B <-C

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

Git实现此目标的方法是Git称为referencerefs 裁判的形式很多,但三巨头是:

  • 分支名称,如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用户交换工作。 为此,我们交换了commits 由于这种密码校验和技巧,它们的哈希ID在所有地方的所有 Git中都是通用的。 给定快照和元数据, 每个地方的每个 Git都会计算相同的哈希ID 因此,如果我的存储库具有这样的提交AH (请记住,这些单个大写字母代表着唯一的,大的丑陋哈希ID),并且我连接到您的存储库并且具有提交H ,则您的存储库还必须具有与矿。

如果您没有提交H ,那么我有您没有提交。 如果你有一些犯I还是J有一个承诺, 不知道。 无论哪种方式,我们的Gits都可以交换哈希ID来查看谁拥有什么。 发送提交的人将发送它们,接收提交的人将接收它们,发送者将向接收者提供任何需要的提交。

假设您正在接受我的新委托。 我有新的提交IJ ,而我的新提交J名称可以记住其哈希ID。 我的存储库中,我有:

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

无论出于什么原因,我都没有像 dev 那样提交F 相反,在(共享)提交E之后,我对我的dev进行了IJ提交。

这是远程跟踪名称的来源

您的Git接受了我的承诺IJ 我的承诺是I有父母E 因此, 您的存储库现在具有以下内容:

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

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

因此,您的Git所做的就是使用远程跟踪名称来记住我的分支。 您的Git会这样做:

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

(假设我的master指向H )。

存储库中的origin/masterorigin/dev名称是您的远程跟踪名称 ,记住了masterdev 4此外,假设您现在查询Git,要求它在Git使用的普通向后走行方法中,比较devorigin/dev可以到达的提交集。

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时,我们将在上一节中对其进行简要介绍。


4 Git有时称其为跟踪,而不是记住 ,但这是Git严重滥用单词的另一个地方。 我已经在远程跟踪中使用了它,但是至少在这里它是带连字符的,并用这个词作为形容词修饰remote


git pushgit fetch不同

上面的过程是您的Git从origin的Git上找到的分支名称创建远程跟踪名称的过程,它特定于git fetch 当你有你的Git调出的Git在它发生origin ,把他们提交给

当然,您可以让您的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并宣布您已提交KH 5他们没有K但是他们有H所以他们让您的Git通过其快照和元数据发送提交K 您的Git可以告诉您,由于它们具有H因此它们也具有GD及其之前的所有内容,因此您只需向他们发送K及其内容。

然后,最后,您的Git询问他们: 请,现在,如果可以,请设置名称newfeature/v4-json指向commit K 请注意,您没有让他们设置xpt/newfeature/v4-json或类似的东西。 您让他们设置了分支! 他们实际上没有newfeature/v4-json ,因此他们可以设置一个。 他们做到了! 现在, 他们的存储库中有一个newfeature/v4-json ,指向commit K

你的Git现在创建 远程跟踪名称 origin/newfeature/v4-json ,指着承诺K ,记住他们的 newfeature/v4-json ,指向提交K 6但这仅表示您的图形中有一个额外的名称 ,如下所示:

                 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)个上游设置,以这种方式使用它非常典型。 请参阅为什么我总是需要执行--set-upstream`吗? 更多。


5您的Git 可以告诉他们有关F ,但前提是您在这里说过git push origin dev 使用带有或不带有-u git push origin newfeature/v4-json ,您告诉Git:根据需要告诉他们有关KHGDCB和/或A提交。 您其他未共享的提交则有意保留为私有。

6请记住,由于哈希ID的魔力,提交K在世界各地的每个 Git中都是通用的。 每个 Git通过其哈希ID都具有K ,然后就是提交; 或者根本没有K ,所以没关系。

(这并不一定是100%的保证。假设的哈希ID K实际上是b5101f929789889c2e536d915698f58d5c5c6b7a ,这是在Git仓库的Git的本身提交的哈希值ID。如果你从来没有你的 Git仓库连接到一个Git仓库GIT中,它是好的,您和他们具有相同的哈希ID的不同提交,但是如果您确实将Git存储库连接到Git的Git存储库,则会发生一些不太理想的事情。简短的版本是您不会Git的提交,而他们却没有得到您的支持:这两个仓库现在根本无法合并,这对您和维护Git的人来说都完全可以,但另请参见新发现的SHA-1碰撞对您的影响git?

暂无
暂无

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

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