简体   繁体   English

如何创建git Remote-Tracking分支

[英]How to create git Remote-Tracking Branch

They said that is it as simple as 他们说这很简单

You can tell Git to track the newly created remote branch simply by using the -u flag with "git push". 您可以简单地通过将-u标志与“ git push”一起使用来告诉Git跟踪新创建的远程分支。

But it never worked for me. 但这对我没有用。

How to create the git Remote-Tracking Branch, with which 如何创建git Remote-Tracking分支

Git can now inform you about "unpushed" and "unpulled" commits. Git现在可以通知您有关“未推动”和“未推动”的提交。

Here is mine: 这是我的:

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

vs what I'm expecting, quoting from 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)

Ie, info about the "unpushed" and "unpulled" commits. 即,有关“未推动”和“未推动”提交的信息。
Ie, I want to see the same as: 即,我希望看到与以下内容相同的内容:

$ 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

Yet from my above actual output, you can see that i'm not able to see how many commits I've made so far anymore, despite that I've made several commits . 但是从上面的实际输出中,您可以看到, 尽管我已经进行了几次提交但我仍然无法看到到目前为止我已经进行了多少次提交

This is what I did: 这是我所做的:

$ 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.

But I don't have such remote tracking branch 'newfeature/v4-json' from 'origin' set up by git : 但是我没有git从'origin'设置的远程跟踪分支'newfeature / v4-json':

A) git remote show origin does not show a remote tracking branch for my newfeature at all: 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)

while the following is what I want to see, according to http://www.gitguys.com/topics/adding-and-removing-remote-branches 根据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)

Note in the Remote branches: section, besides master tracked , there is also a newfeature tracked . 请注意,在“ Remote branches:部分中,除了master tracked外,还master tracked了一个newfeature tracked This newfeature tracked is called remote tracking branch as per above article. 根据上述文章,被跟踪的 newfeature tracked称为远程跟踪分支

B) neither is git branch -a : B) git branch -a都不是:

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

There is only one remotes/origin/master remote tracking name there, while I'm expecting more. 那里只有一个remotes/origin/master远程跟踪名称,而我期望更多。 Eg (irrelevant but just to show the case with more remote tracking names), 例如(无关紧要,只是为了显示具有更多远程跟踪名称的情况),

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

C) nor is git branch -vv : C) git branch -vv也不是:

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

while I'm expecting to see, 我希望看到,

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

Moreover, 此外,

git pull is not updating my local branch from remote either: 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.

Ie, no matter how many time I pull, I'm not getting the same output as, 就是说,无论我拉多少次,我都不会得到相同的输出,

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

All above is not normal. 以上都是正常的。 I've created Remote-Tracking Branch with MS VS before many times, and the results are exactly as what I am expecting, not above. 我已经使用MS VS多次创建了Remote-Tracking Branch,其结果完全符合我的预期,而不是上面的预期。 However, I don't like the black magic tricks, so I want to know how I can do the same with plain git . 但是,我不喜欢黑魔术,所以我想知道如何使用纯git来做同样的事情。

So what is the correct way to create git Remote-Tracking Branch? 那么创建git Remote-Tracking Branch的正确方法是什么?

Edit to address updated ( git branch -a and git branch -vv ) output: yes, something is missing. 编辑以更新地址( git branch -agit branch -vv )输出:是的,缺少某些内容 It's not entirely clear what went wrong, but I have a guess. 目前还不清楚到底出了什么问题,但我有一个猜测。 This part of the git push -u output: 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. 

shows your Git setting your origin/newfeature/v4-json (split into two parts) as your upstream for newfeature/v4-json . 显示您的Git将您的origin/newfeature/v4-json (分为两部分)设置为newfeature/v4-json上游。 But your git branch -a and git branch -vv output show that origin/newfeature/v4-json is not there. 但是您的git branch -agit branch -vv输出显示不存在origin/newfeature/v4-json

I can reproduce a key element of this behavior by making a single-branch clone. 我可以通过进行单分支克隆来重现此行为的关键要素。 Using git clone --depth= number or git clone --single-branch will produce such a clone. 使用git clone --depth= numbergit clone --single-branch将产生这样的克隆。 The side effect of this is that your Git will never create any remote-tracking names for any branch other than the one branch you told Git that you were concerned with. 这样做的副作用是,您的Git将永远不会为任何分支创建任何远程跟踪名称, 除非您告诉Git所关心的那个分支。 If this is the problem, the fix is to convert the clone to a normal (multi-branch) clone. 如果这问题所在,则解决方法是将克隆转换为普通(多分支)克隆。 (If you used --depth to create the single-branch aspect, it may also be wise to unshallow the clone.) (如果使用--depth创建单分支方面,则取消克隆该副本也是明智的。)

To see if your clone of origin is set to be single-branch: 要查看您的origin克隆是否设置为单分支:

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

In a normal clone, this will print: 在普通克隆中,将打印:

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

In a single-branch clone with the branch master chosen, this will print: 在选择了分支master的单分支克隆中,将打印:

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

which tells your Git: create a remote-tracking name for master rather than the former's create remote-tracking names for * , ie, all branches . 它告诉您的Git: master创建一个远程跟踪名称,而不是* (即所有分支)创建前者的远程跟踪名称

To un-do the single-branch-ness of a clone of origin : 取消origin克隆的单分支:

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

(or edit .git/config directly, eg, git config --edit , which is my preferred method). (或直接编辑.git/config ,例如git config --edit ,这是我的首选方法)。 See also How do I "undo" a --single-branch clone? 另请参阅如何“撤消”-单分支克隆?

To convert a shallow clone to a full (non-shallow) clone, just run: 要将浅层克隆转换为完整(非浅层)克隆,只需运行:

$ git fetch --unshallow

Note that this operation is independent of single-branch-ness, despite the way git clone ties them together by default (you can override this at git clone time with git clone --depth= number --no-single-branch ). 请注意,尽管git clone默认将它们git clone --depth= number --no-single-branch在一起,但此操作与单分支无关(您可以在git clone时使用git clone --depth= number --no-single-branch覆盖此操作)。 There is no command-line test for shallow-ness in versions of Git before 2.15; 在2.15之前的版本中,没有针对浅薄度的命令行测试; in 2.15 or later, use: 在2.15或更高版本中,使用:

git rev-parse --is-shallow-repository

but before then you have to test for the existence of the file .git/shallow : 但在此之前,您必须测试文件.git/shallow的存在:

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

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

As an aside, there is a problem with the output you want to see. 顺便说一句,您查看的输出存在问题。 You say that you'd like to see newfeature as a branch on the remote—but that cannot happen as the name newfeature/v4-json needs to exist, which precludes the ability for newfeature to exist. 您说您想将newfeature看作是远程服务器上的一个分支,但这不会发生,因为需要存在newfeature/v4-json名称,这排除了newfeature的存在能力。

(Original answer below line.) (以下行的原始答案。)


 $ git push -u origin newfeature/v4-json 

This worked exactly as you asked it to. 这完全按照您的要求进行。 Everything is just fine in the rest of the output that you showed. 在您显示的其余输出中,一切都很好。 So it's not clear what you think is wrong; 因此,尚不清楚您认为错在哪里; nothing is actually wrong. 其实没有错。 I'll address the other message you showed: 我将解决您显示的其他消息:

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

below. 下面。

What does all this mean? 这是什么意思呢? (Long) (长)

It may help to review how Git works and some of Git's rather peculiar terminology. 回顾一下Git的工作方式和一些Git特有的术语可能会有所帮助。 In particular, the phrase you're using— remote-tracking branch —is, in my opinion, a bad term, actively misleading. 我认为,特别是,您使用的短语- 远程跟踪分支 -是一个词,会引起误解。 It is a Git term, so we should understand what people mean when they use it, but it's a bad term, which means that people misuse it, and if you're confused by someone's usage, it may be worth stepping back and considering these things again. 一个Git术语,所以我们应该理解人们在使用它时的含义,但这是一个不好的术语,这意味着人们会滥用它,如果您对某人的使用感到困惑,那么可能应该退一步并考虑一下这些事情再次发生。

First, let's note that Git is really all about commits . 首先,让我们注意Git实际上就是关于commit的全部内容。 Commits are Git's raison d'être ; 承诺是Git的存在理由 without commits, we wouldn't use Git at all. 没有提交,我们根本不会使用Git。 So let's look at what a commit is. 因此,让我们看看什么是提交。

Each commit contains files, but it's not just a set of files. 每个提交都包含文件,但不仅仅是一组文件。 It's a snapshot, of all of your files as of the time you took the snapshot, 1 but it also has some metadata: information about the stored data. 它是快照中所有文件的快照, 1但它也包含一些元数据: 有关存储数据的信息。 The most obvious is the stuff you see in git log output: your name and email address, and the computer's idea of what day and time it was when you made the commit, along with the reason you saved for making the commit, ie, your log message. 最明显的是您在git log输出中看到的内容:您的姓名和电子邮件地址,以及计算机对您进行提交的日期和时间的想法,以及为进行提交而保存的原因 ,即您的日志消息。 These are all meant for you—or someone else—to use in the future: someday, perhaps tomorrow, perhaps months or years from now, you may look back at this commit you just made, and ask yourself: why the heck did I do that ? 这些都是供您(或其他人)将来使用的:某天,也许明天,也许几个月或几年之后,您可以回顾一下您刚才所做的提交,并问自己: 我为什么要做 The answer should be in your log message. 答案应该在您的日志消息中。

Because a commit stores files—as a snapshot, frozen in time, immutable, and living forever (or as long as the commit itself lives)—they're great for archival. 因为提交存储文件(作为快照,时间冻结,不可变并且可以永久存在(或只要提交本身一直存在)),所以非常适合归档。 Any time in the future, you can go back into the past and see exactly what you saved back then. 在将来的任何时候,您都可以回顾过去,并准确地查看当时保存的内容。 You can't change it: it's in the past, fixed, frozen in time. 您无法更改:它是过去的,固定的,已冻结的时间。 Not even Git can change it, as we'll see in a moment. 稍后我们将看到,即使Git也无法更改它。

In order to find a commit, Git needs a name. 为了找到提交,Git需要一个名称。 These names are not branch names! 这些名称不是分支名称! Or, more accurately, you can start out using a branch name, but that's not the name that Git needs. 或者,更准确地说,您可以使用分支名称开始,但这不是Git所需的名称。 The true name of any commit is instead its hash ID . 相反,任何提交的真实名称是其哈希ID The hash ID of each commit seems random, but in fact, it's a cryptographic checksum of the entire contents of the commit, exquisitely sensitive to every single bit of data in that commit: all of the frozen snapshot, and also your name and the time-stamp and your log message. 每个提交的哈希值ID 似乎是随机的,但实际上,它是上提交的全部内容的加密校验,以提交数据的每一个位极其敏感:所有冻结的快照,并您的姓名和时间-stamp和您的日志消息。 That's why you, or anyone, can't change a commit: changing anything changes the hash ID, and what you then have is a new and different commit. 这就是为什么您或任何人都不能更改提交的原因:更改任何内容都会更改哈希ID,然后您将拥有一个新的不同的提交。 Nobody knows what the hash ID will be for a new commit until it's made. 在进行提交之前,没人知道哈希ID是什么。 At that time, it gets a unique ID. 当时,它获得了唯一的ID。 No one will ever use that ID for any other commit! 没有人会将该ID用于其他任何提交! And no one can change anything in the commit: Git will know if you try because the ID won't match up any more. 没有人可以改变什么提交:Git会知道,如果你尝试,因为该ID不匹配了。 2 2

There's one or two last key pieces to this particular jigsaw puzzle. 这个特殊的拼图游戏有最后一两个关键部分。 The first is that within each new commit, Git stores the hash ID—the true name—of the previous commit, as part of that metadata. 第一个是,在每个提交中,Git都将前一次提交的哈希ID(真实名称)存储为该元数据的一部分。 That is, Git does not just save your name and the time and so on, but also saves the raw hash ID of the commit you used to make this new commit. 也就是说,Git不会只是保存您的姓名和时间等,同时也节省了您的使用使这个新提交的提交的原始哈希ID。 Git calls this saved hash ID the parent of the commit. Git将此保存的哈希ID称为提交的父级 What this means is that each commit points to its parent commit, in a backwards-looking chain. 这意味着每个提交都在向后看的链中指向其父提交。

For instance, suppose we have just two commits A and B in a repository. 例如,假设我们在存储库中只有两个提交AB A is the very first commit so it deliberately has no parent—it's a special case. A是第一个提交,因此特意没有父提交-这是特例。 But B was made from A , so B points back to A : 但是B是由A制成A ,因此B指向A

A <-B

If you extract commit B , do some work, and make a new commit C , the new commit automatically points back to B : 如果您提取提交B ,执行一些工作,然后进行新的提交C ,则新的提交将自动指向B

A <-B <-C

What this means is that Git only needs to know the apparently-random hash ID of the last commit. 意味着Git只需要知道最后一次提交的表面上随机的哈希ID。 In this case that's commit C . 在这种情况下,提交C If its actual hash ID is cba9876... or whatever, Git can use that to find the contents of C . 如果其实际的哈希ID是cba9876...或其他值,Git可以使用它来查找C内容 Those contents include the actual hash ID of commit B . 这些内容包括提交B的实际哈希ID。 Git can then use that to find B , whose contents include the actual hash ID of commit A . 然后,Git可以使用它来查找B ,其内容包括提交A的实际哈希ID。 Git can use that to find A , and A has no parent, so now, finally, Git can stop working backwards. Git可以使用它来查找A ,而A没有父母,所以现在,Git终于可以停止向后工作。

This process of working backwards from a branch tip commit like C , identified by a branch name , is crucial in Git. 分支提示提交(例如,由分支名称标识的C向后工作的过程在Git中至关重要。 It's how history exists . 历史就是这样存在的 The history in a Git repository is the commits, as connected by these backwards-pointing arrows. Git存储库中的历史记录提交,这些提交通过这些向后的箭头连接。 You start from the end and walk, one commit at a time, through history, to see where you can reach by following the parent arrows. 您从头开始,一次走动一次,遍历历史,按照父箭头查看可以到达的位置。

This is where the last jigsaw-puzzle piece enters the picture, when branch names and other such names show up. 分支名称和其他此类名称显示出来时,这是最后一个拼图碎片输入图片的地方。 Let's take a pause and finish off the footnotes here, then dive into branch names and graph-drawing. 让我们暂停一下,在这里结束脚注,然后深入研究分支名称和图形绘制。


1 Git actually makes the snapshot from the index , but we won't get into these details here, other than to say that what gets snapshotted—frozen in time, forever, for that commit—is whatever is in the index at the time, which is at least potentially different from what you can see in your work-tree where you do your work. 1 Git实际上是从索引制作快照的,但是我们不会在这里介绍这些细节,除了说要快照的内容(对于该提交,永远冻结的时间)就是当时索引中的内容,这至少可能与您在工作树中看到的内容有所不同。

2 Git actually does check this, whenever it seems convenient or appropriate. 2 Git实际上会在方便或适当的时候进行检查。 That automatically detects accidental corruption of a Git repository, as occurs when (eg) you try to store on in Dropbox—Dropbox sometimes goes around modifying files behind your (and Git's) back, and Git catches it. 这会自动检测到Git存储库的意外损坏,例如在您尝试将其存储在Dropbox中时发生的情况。Dropbox有时会四处修改(和Git的)背后的文件,而Git会抓住它。 Unfortunately, there's rarely a good way to repair a corrupted repository—instead, Git tends to rely on the idea that Git repositories get replicated all over the place. 不幸的是,很少有修复损坏的存储库的好方法-而是,Git倾向于依赖Git存储库在各处复制的想法。 You probably have a good copy somewhere else so you just throw this one out entirely. 您可能在其他地方有一份不错的副本,因此您完全可以将其扔掉。


Branch names find commit hash IDs 分支名称查找提交哈希ID

Any existing repository—well, any one other than a totally empty, fresh, new repository with no commits in it yet—has some set of commits. 任何现有的存储库(好吧,除了一个完全空的,新鲜的, 没有提交的新存储库之外的任何其他存储库)都具有一组提交。 These commits form the backwards-looking chains we just saw, such as: 这些提交构成了我们刚刚看到的向后看的链,例如:

A <-B <-C

We—and Git—need some way to record the hash ID of the last commit in this chain. 我们和Git需要某种方式来记录该链中最后一次提交的哈希ID。

The way Git achieves this is with what Git calls references or refs . Git实现此目标的方法是Git称为referencerefs There are many forms of refs, but the Big Three are: 裁判的形式很多,但三巨头是:

  • Branch names, like master . 分支名称,如master
  • Remote-tracking names, like origin/master . 远程跟踪名称,例如origin/master (Git calls these remote-tracking branch names or remote-tracking branches , which I think is a bad name; I've switched to using remote-tracking names , which I think is harder to get wrong.) (Git称这些远程跟踪分支名称远程跟踪分支 ,我认为这是一个坏名字;我已改用远程跟踪名称 ,我认为这很难弄错。)
  • Tag names, like v1.3 . 标签名称,如v1.3

They are actually all implemented by the same underlying techniques, but we'll just treat them as separate forms of name here. 它们实际上都是由相同的基础技术实现的,但在这里我们将它们视为单独的名称形式。 Branch names have a special property; 分支名称具有特殊属性; all the other names lack this property. 所有其他名称都缺少此属性。

What goes in one of these names is quite simple: it's just the actual raw hash ID of a Git object, typically a commit. 这些名称之一的含义非常简单:它只是Git对象的实际原始哈希ID,通常是提交。 3 So a branch name like master points to the last commit in the branch—commit C in this drawing: 3因此,像master这样的分支名称指向分支最后一个提交-在此图形中提交C

A--B--C   <-- master

Note that the arrows that connect commits to each other come out of the child and point back to the (immutable) parent, giving us this backwards traversal method. 请注意,相互连接的箭头从子对象中出来并指向(不可变的)父对象,这为我们提供了这种向后遍历的方法。 We don't have to bother to draw them in. The arrows coming out of branch names, however, change . 我们不必费心将它们插入。但是, 分支名称中的箭头会更改

When we add a new commit to master , Git automatically updates the name master to hold the new commit's hash ID. 当我们向master添加新的提交时,Git会自动更新名称master来保存新提交的哈希ID。 So if we create a new commit now, the new commit D will point back to C : 因此,如果我们现在创建一个新的提交,则新的提交D将指向C

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

but Git will immediately adjust master to point not to C but to D : 但是Git会立即调整master使其不指向C而是指向D

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

Since D points back to C , we can still find all the commits: we start at the end, and work backwards as usual. 由于D指向C ,我们仍然可以找到所有提交:我们从结尾开始,然后像往常一样向后工作。 C is now the second commit in this process instead of the first. 现在, C是此过程中的第二个提交,而不是第一个。


3 Branch names must hold commit object hash IDs, while tag names are more flexible. 3分支名称必须包含提交对象哈希ID,而标记名称则更灵活。 We don't need to care about this here. 我们在这里不需要关心这一点。 Because remote-tracking names' values are copied from branch names, remote-tracking names also hold only commit hash IDs. 因为远程跟踪名称的值是分支名称中复制的,所以远程跟踪名称也仅包含提交哈希ID。


Branch names are private to each repository, but repositories talk to each other 分支名称是每个存储库专用的,但是存储库彼此通信

Git is a distributed version control system. Git是一个分布式版本控制系统。 This means that each Git repository is a sort of self-contained island, with everything it needs local to that repository. 这意味着每个Git存储库都是一种独立的孤岛,它需要的所有内容都在该存储库本地。 If there are multiple branches with many commits, they are all in that one repository: 如果有许多提交多个分支机构,他们在一个存储库:

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

To make Git really useful, we regularly use Git to exchange work with other Git users. 为了使Git真正有用,我们定期使用Git与其他Git用户交换工作。 To achieve that, we exchange commits . 为此,我们交换了commits Their hash IDs are universal across all Gits everywhere, because of that cryptographic checksum trick. 由于这种密码校验和技巧,它们的哈希ID在所有地方的所有 Git中都是通用的。 Given a snapshot and metadata, every Git everywhere will compute the same hash ID . 给定快照和元数据, 每个地方的每个 Git都会计算相同的哈希ID So if my repository has commits A through H like this—remember that these single uppercase letters are standing in for unique, big ugly hash IDs—and I connect to your repository and you have commit H , your repository must also have the same commit as mine. 因此,如果我的存储库具有这样的提交AH (请记住,这些单个大写字母代表着唯一的,大的丑陋哈希ID),并且我连接到您的存储库并且具有提交H ,则您的存储库还必须具有与矿。

If you don't have commit H , I have a commit that you don't. 如果您没有提交H ,那么我有您没有提交。 If you have some commit I or J , you have a commit that I don't. 如果你有一些犯I还是J有一个承诺, 不知道。 Either way, our Gits can just exchange hash IDs to see who has what. 无论哪种方式,我们的Gits都可以交换哈希ID来查看谁拥有什么。 Whoever is sending commits will send them, whoever is receiving commits will receive them, and the sender will give the receiver any new commits needed. 发送提交的人将发送它们,接收提交的人将接收它们,发送者将向接收者提供任何需要的提交。

Let's say you are taking new commits from me. 假设您正在接受我的新委托。 I have new commits I and J , and my new commit J has a name that remembers its hash ID. 我有新的提交IJ ,而我的新提交J名称可以记住其哈希ID。 In my repository, I have this: 我的存储库中,我有:

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

For whatever reason, I don't have commit F that you have on dev . 无论出于什么原因,我都没有像 dev 那样提交F Instead, I have my IJ commits on my dev , after (shared) commit E . 相反,在(共享)提交E之后,我对我的dev进行了IJ提交。

This is where remote-tracking names come in 这是远程跟踪名称的来源

Your Git takes my commits I and J . 您的Git接受了我的承诺IJ My commit I has parent E . 我的承诺是I有父母E So your repository now has this: 因此, 您的存储库现在具有以下内容:

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

What name will your Git repository use to remember my commit I ? 您的 Git存储库将使用什么名字来记住我的提交I It had better not use dev : if your Git makes your dev point to commit I , how will you ever find commit F again? 最好不要使用dev :如果您的Git使您的dev指向commit I ,您将如何再次找到commit F Remember, it has an apparently-random hash ID. 请记住,它具有一个显然是随机的哈希ID。 You'll never be able to guess it. 您将永远无法猜测

So, what your Git does is use remote-tracking names to remember my branches. 因此,您的Git所做的就是使用远程跟踪名称来记住我的分支。 Your Git does this: 您的Git会这样做:

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

(assuming my master points to commit H ). (假设我的master指向H )。

The names origin/master and origin/dev in your repository are (your) remote-tracking names , remembering my master and my dev . 存储库中的origin/masterorigin/dev名称是您的远程跟踪名称 ,记住了masterdev 4 Moreover, suppose you now query your Git, asking it to compare the set of commits reachable from dev vs those from origin/dev , in the ordinary walk-backwards method that Git uses. 4此外,假设您现在查询Git,要求它在Git使用的普通向后走行方法中,比较devorigin/dev可以到达的提交集。

Starting from dev , the commits you will visit are F , then E , then D , and so on back to A . dev开始,将要访问的提交是F ,然后是E ,然后是D ,依次类推回到A Starting from origin/dev , the commits you will visit are J , then I , then E , then D , and so on back to A . origin/dev ,将要访问的提交是J ,然后是I ,然后是E ,然后是D ,依次类推回到A Which commits are unique to which walk? 哪些提交是哪个步行特有的? How many commits do you reach from dev that you can't reach from origin/dev , and vice versa? 您从dev到达的提交数量是您从origin/dev不能到达的提交数量,反之亦然?

Count those out, and then compare to what your Git told you: 算出这些,然后与您的Git告诉您的内容进行比较:

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

There's actually another piece missing from our jigsaw puzzle here which we'll just describe lightly in the last section when we talk about git push below. 实际上,这里的拼图游戏还缺少另一部分,当我们在下面谈论git push时,我们将在上一节中对其进行简要介绍。


4 Git sometimes calls this tracking rather than remembering , but this is another place Git badly overuses a word. 4 Git有时称其为跟踪,而不是记住 ,但这是Git严重滥用单词的另一个地方。 I've used it in the phrase remote-tracking , but at least here it's hyphenated and uses the word as an adjective modifying remote . 我已经在远程跟踪中使用了它,但是至少在这里它是带连字符的,并用这个词作为形容词修饰remote


git push is different from git fetch git pushgit fetch不同

The process above, where your Git created remote-tracking names from the branch names found on the Git at origin , is specific to git fetch . 上面的过程是您的Git从origin的Git上找到的分支名称创建远程跟踪名称的过程,它特定于git fetch It happens when you have your Git call up the Git at origin and bring their commits to you . 当你有你的Git调出的Git在它发生origin ,把他们提交给

You can, of course, have your Git call up their Git at origin and send commits. 当然,您可以让您的Git在origin调用他们的Git并发送提交。 That's the git push operation, and it's pretty similar. 这就是git push操作,非常相似。 Your Git tells their Git about the commits that you have, that they don't. 您的Git告诉他们的Git您所拥有的提交,而他们没有。 Let's draw some. 让我们画一些。 We'll start with this: 我们将从此开始:

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

Now we'll run git checkout master and git checkout -b newfeature/v4-json , or the simpler: 现在,我们将运行git checkout mastergit checkout -b newfeature/v4-json或更简单的命令:

git checkout -b newfeature/v4-json master

We now have: 现在,我们有:

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

We've attached the special name HEAD to newfeature/v4-json to remember which branch name gets updated as we add new commits. 我们已经将特殊名称HEAD附加到newfeature/v4-json以记住添加新提交时更新哪个分支名称。

Now we'll create one new commit. 现在,我们将创建一个新提交。 It could be more than one, or even none , but let's just create one for illustration. 它可能不止一个,甚至没有一个 ,但我们只创建一个用于说明。 The new commit gets some big ugly hash ID, but we'll just call it K here: 新的提交有一些大的丑陋的哈希ID,但我们在这里将其称为K

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

Now we will have your Git call up the Git at origin , using: 现在,我们将使用以下命令让您的Git在origin调用Git:

git push -u origin newfeature/v4-json

Your Git dials up their Git and announces that you have commits K and H . 您的Git拨号他们的Git并宣布您已提交KH 5 They don't have K but they do have H so they have your Git send over commit K with its snapshot and metadata. 5他们没有K但是他们有H所以他们让您的Git通过其快照和元数据发送提交K Your Git can tell that since they have H they also have G and D and everything before that, so you only have to send them K and its contents. 您的Git可以告诉您,由于它们具有H因此它们也具有GD及其之前的所有内容,因此您只需向他们发送K及其内容。

Then, at the end, your Git asks them: Please, now, if it's OK, set your name newfeature/v4-json to point to commit K . 然后,最后,您的Git询问他们: 请,现在,如果可以,请设置名称newfeature/v4-json指向commit K Note that you don't have them set xpt/newfeature/v4-json or anything like that. 请注意,您没有让他们设置xpt/newfeature/v4-json或类似的东西。 You have them set their branch! 您让他们设置了分支! They don't actually have a newfeature/v4-json yet, so it's quite OK for them to set one. 他们实际上没有newfeature/v4-json ,因此他们可以设置一个。 So they do! 他们做到了! They now have a newfeature/v4-json in their repository, pointing to commit K . 现在, 他们的存储库中有一个newfeature/v4-json ,指向commit K

Your Git now creates your remote-tracking name origin/newfeature/v4-json , pointing to commit K , to remember their newfeature/v4-json , pointing to commit K . 你的Git现在创建 远程跟踪名称 origin/newfeature/v4-json ,指着承诺K ,记住他们的 newfeature/v4-json ,指向提交K 6 But that just means that your graph has one extra name in it, like this: 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

Because of the -u option, your Git immediately also runs: 由于使用-u选项,您的Git也会立即运行:

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

This sets the upstream setting for your branch newfeature/v4-json . 这将为分支newfeature/v4-json设置上游设置。 Each of your branches can have one (1) upstream setting, and it's pretty typical to use it in just this way. 您的每个分支都可以具有 (1)个上游设置,以这种方式使用它非常典型。 See Why do I need to do `--set-upstream` all the time? 请参阅为什么我总是需要执行--set-upstream`吗? for more. 更多。


5 Your Git could tell them about F , but only would have if you had said git push origin dev here. 5您的Git 可以告诉他们有关F ,但前提是您在这里说过git push origin dev Using git push origin newfeature/v4-json , with or without -u , you told your Git: Tell them about commits K , H , G , D , C , B , and/or A as needed. 使用带有或不带有-u git push origin newfeature/v4-json ,您告诉Git:根据需要告诉他们有关KHGDCB和/或A提交。 Your other unshared commits remain private, on purpose. 您其他未共享的提交则有意保留为私有。

6 Remember, due to the magic of hash IDs, commit K is universal across every Git everywhere . 6请记住,由于哈希ID的魔力,提交K在世界各地的每个 Git中都是通用的。 Every Git either has K , by its hash ID, and then it's that commit; 每个 Git通过其哈希ID都具有K ,然后就是提交; or doesn't have K at all, so that it doesn't matter. 或者根本没有K ,所以没关系。

(This isn't necessarily 100% guaranteed. Suppose the hash ID of K is actually b5101f929789889c2e536d915698f58d5c5c6b7a . That's the hash ID of a commit in the Git repository for Git itself. If you never connect your Git repository to a Git repository for Git, it's OK that you and they have different commits with the same hash ID. But if you do ever connect your Git repository to a Git repository for Git, some not-so-great things happen. The short version is that you just don't get Git's commit and they just don't get yours: the two repositories simply cannot be combined at this point. That is probably completely fine with both you and the people who maintain Git. But see also How does the newly found SHA-1 collision affect Git? ) (这并不一定是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.

相关问题 Git:如何获取单个远程分支并自动创建远程跟踪分支? - Git: How to fetch a single remote branch and create a remote-tracking branch of it automatically? 如何在Git中不预先合并远程跟踪提交的情况下创建新分支? - How to create a new branch without pre-merge remote-tracking commits in Git? Git - 推送到远程存储库中的远程跟踪分支 - Git - push to a remote-tracking branch in the remote repository 通过一个Git远程跟踪分支的名字如何找到本地分支跟踪它? - By given name of a Git remote-tracking branch how to find which local branch tracks it? 当使用git删除相应的本地分支时,如何自动删除远程跟踪分支 - How to automatically remove remote-tracking branch when the corresponding local branch is removed using git Git:如何将“合并远程跟踪分支”改造并压缩到后来的提交中? - Git: How to rebase and squash “Merge remote-tracking branch” to the later commit? 如何合并远程跟踪none github分支? - How to merge remote-tracking a none github branch? 如何将远程跟踪分支“ caffe / master”合并到HEAD中? - how to Merge remote-tracking branch 'caffe/master' into HEAD ? 如何更改远程跟踪分支指向的提交? - How can I change the commit a remote-tracking branch points to? 删除远程分支时如何删除本地远程跟踪分支? - How do I delete local remote-tracking branches when remote branch is deleted?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM