我正在学习Git并试图理解“跟踪”远程和定义“上游”关系(使用-u
标记)之间的区别。
对于master to origin / master,我一直在使用
git push origin master
似乎自动定义了一种关系(虽然我不确定它是什么)。
对于分支机构,我一直在使用
git branch newbranch
git push -u origin newbranch
我知道这会设置一个上游关系,但我再也不理解这种区别。
有人可以解释一下这个区别吗?
答案 0 :(得分:10)
这里的两个答案都是正确的,但我会描述潜在的机制,因为在我发现它是什么之前,我发现了"追踪"的全部概念。非常神秘。
Git打破这个"追踪"信息分为两部分:遥控器的名称 - 通常是单词 如果您查看了 但是这个跟踪分支的内容还有一个部分:当你运行 实际上 所有这些中的古怪是 因此,以此为背景,让我们看一些命令: 第二种最简单的refspec形式只是两个分支名称,它们之间有一个冒号,如 如果你给出一半" refspec"像 如果您提供更全面的refspec,例如 git有更聪明的技巧: 如果您运行 如果您运行 摘要: 还有一个有趣的转折:任何分支"上游"可以在您自己的本地存储库中。为此,您将该分支的 Mercurial用户可能想知道如何获得 换句话说,如果您依靠 如上所述,在您在相应的遥控器上运行 所以: (在某些shell中,您可能需要 当然,您可以将 1 如果您的分支机构名称与他们的名称相同,则您将无法看到此分支。但是一旦你开始大量使用分支机构,你可能会找到几个跟踪上游相同的分支机构,然后它真的很重要。 2 3 如果你的git版本早于1.8.4,那么当 4 在编辑中修复:我不小心写了origin
,就像您正在使用 - 然后是远程上的git命令用于命名分支的名称。 1 换句话说,如果您具有对远程的登录访问权限,并且您在那里登录并进入存储库,则可以运行git log master
以查看已提交的内容。< / p>
.git/config
文件,您会看到,对于每个本地分支机构来说,&#34;跟踪&#34;什么,这两部分。例如,假设您有一个名为experiment
的本地分支,您已将其设置为跟踪origin/master
。这将导致:[branch "experiment"]
remote = origin
merge = master
git fetch origin
时,master
上的分支origin
上有新内容,fetch
1}}步骤更新您的本地origin/master
。这个名称 - 首先是远程名称origin
,然后是斜杠/
,然后是遥控器上显示的分支名称,就是如何看到遥控器上发生了什么。完成git fetch
后,它会将远程的分支名称(以及它们的分支提示的相应SHA-1)复制到本地存储库,并使用前面的远程名称重命名它们。 / p>
git fetch
步骤更新了origin/master
等等,只有在完成后才会执行此操作,并且&#34;跟踪&#34;东西有任何有用的效果。 Git现在可以通过一些提交告诉你,你已经提前和/或落后了。而且,您现在可以运行git log origin/master
之类的命令,看看那里发生了什么 - 或者更有趣的是,git log --oneline master..origin/master
看看&#34;他们的&#34;承诺你还没有:基本上,&#34; fetch带来了什么&#34; - 和git log --oneline origin/master..master
来看&#34;你的&#34;承诺他们还没有。 (如果你已经完成了合并或重组,那么看看你的fetch带来了什么已经太晚了,因为现在你已经拥有了他们所拥有的东西,这是因为你的合并或重组。) git pull
。 git pull
命令实际上只是首先运行git fetch
的快捷方式,然后运行git merge
(或者,如果您重定向它,git rebase
)。要单独执行这些步骤,请运行git fetch origin
,然后git merge origin/master
或git rebase origin/master
。由于历史原因, 2 git pull
获取分支的远程名称,在本例中为master
,而不是名称它最终被重命名为你的存储库。
<等等,什么是refspec?
git fetch remote
:根本不需要任何分支名称。它调用给定的远程,询问它现在所有分支的位置,并更新您的存储库,在origin/
名称下记录所有这些更新(以免影响任何本地分支)。换句话说,这会更新您的分支机构可能(或可能不会)跟踪的名称,但它不需要知道什么是或不跟踪什么。git status
:如果它在分支X&#34;上表示您已经&#34;并且分支 X
正在跟踪{{1 }},origin/X
还可以告诉您,如果您在 git status
上提交了不在X
上的提交,反之亦然。origin/X
和git merge
:这些需要一些方法来了解要合并的内容或者要重新绑定的内容。您可以明确地命名,但如果您告诉您的git您的分支git rebase
正在跟踪X
,那么无论何时您在分支origin/X
,X
或{ {1}}会知道该怎么做。git merge
:这是设置或更改当前分支跟踪内容的主要命令。换句话说,如果您现在在分支git rebase
上,则会为您更新git branch --set-upstream-to origin/X
和X
,这样您就不必使用两个单独的{{} 1}}命令。您还可以使用branch.X.remote
删除跟踪信息。branch.X.merge
:如果您没有提供其他信息,它会使用当前分支&#34;远程&#34; - 其跟踪信息的前半部分 - 来决定哪个远程信息打电话来。无论您是否给git config
一个远程名称,下一部分取决于您是否给它一个&#34; refspec&#34;。如果您不这样做,git branch --unset-upstream
使用git push
来决定使用哪种refspec。git push
。对于git push
,左侧的名称是您的分支名称,右侧的名称是他们的另一个git&#39; s-branch名称。如果省略push.default
,您将得到最简单的表单,其中远程端名称 - 跟随master:master
的名称 - 由一个稍微复杂的过程选择(在git push
documentation中描述) ),这实际上取决于更多的配置变量以及您是否设置了上游。git push
怎么样?这只是一个方便的快捷方式::
是执行两个:
命令的快捷方式,git push -u
是执行推送的快捷方式,然后执行操作git branch --set-upstream-to
也是如此。你必须给git config
一个refspec来做这件事。git push -u refspec
?好吧,如上所述,git选择提供给远程git的名称是通过一个复杂的过程找到的,但如果你还没有设置上游(这是如果您首先进行git branch --set-upstream-to
,那么它很可能会与您的本地名称相同。所以push
可能&#34;意味着&#34;最后,master
和 表示git push -u
。git push -u origin master
,则会将git push -u origin master:master
分支推送到git branch --set-upstream-to origin/master
,要求git push -u origin experiment:feature
将其称为experiment
,并且然后做一个origin
。请注意,此时,本地分支的上游名称与本地名称不同。 Git对此很好;只要确定你也是。 : - )
origin
并且 feature
尚不存在,那么和就是单个&#34; &明显#34;远程跟踪分支,例如--set-upstream-to origin/feature
,git将创建一个已经跟踪git checkout branch
的新的本地 branch
。 (也就是说,本地分支的origin/branch
设置为branch
,其origin/branch
设置为 remote
。)origin
,git会自动设置本地分支以跟踪相应的远程跟踪分支。 (您可以配置git是否要这样,但这是默认设置。)merge
更新跟踪使用的内容(branch
条目,用于远程git branch local-name remote-tracking-name
)。完成后 - 包括使用git fetch
运行origin/*
3 - 然后完成后,您会看到来自origin
等命令的更多信息;和git pull
之类的命令使用它来知道如何进行rebase,而不必再告诉它了。git fetch
设置为git status
(文字点),将git rebase
设置为分支的名称。您不必知道如何执行此操作,因为您可以执行remote
,例如,让您当前的分支跟踪您自己的.
。&#34;传入&#34;和&#34;传出&#34;
merge
或git branch --set-upstream-to master
的效果。前者告诉你你的上游有什么,你没有。后者告诉你你有什么,他们没有。事实证明,这在现代git中很容易实现,因为git有一个特殊的语法master
,用于查找当前分支的上游。hg incoming
和hg outgoing
跟踪@{u}
,master
(您可以将其拼写为master
)只是写origin/master
的另一种方式。因此,@{u}
只是编写@{upstream}
的更长方式。 和,如果您origin/master
,origin/master..master
也会命名@{u}..master
,省略分支名称会告诉git使用master
,所以HEAD
就足够了。master
后,您可以使用HEAD
来查找他们所拥有的内容,而不是&#t;#34 ;和&#34;你拥有的他们没有&#34;。您必须运行此@{u}..
步骤(并且不希望此时发生合并或重新绑定)。git fetch
git log
前面的git fetch
或其他引用技巧,通过运行{{1}可能更容易在编辑器中插入别名})。git config --global alias.incoming '!git fetch && git log --oneline ..@{u}'
git config --global alias.outgoing '!git fetch && git log --oneline @{u}..'
部分更改为您喜欢的任何选项。 (而且我喜欢离开\
步骤让我自己手动运行自己,例如,将别名简化为!
。 4 这主要是为了避免不断纠缠上游。)git config --global --edit
实际上早于远程和远程跟踪分支。由于这个原因,它仍然有各种各样的怪异。--oneline
运行git fetch
时,alias.incoming = log --oneline ..@{u}
步不会更新远程跟踪分支。这是一个功能,但它是一个糟糕的功能,更新的git版本更新。但这确实意味着,如果你有一个旧的git,你应该警惕使用git pull
脚本:这是一个不方便的方便。git pull
。假设Git别名是其他git命令(如git fetch
),因此您希望省略 fetch
部分,除非整个别名以感叹号pull
开头,在这种情况下,整个别名将传递给shell运行。我现在忘记了,当所有命令拼写为alias.incoming = git log ...
,log
,git
等时,别名如何处理,但它一定不那么复杂......: - )
答案 1 :(得分:8)
git push origin master
明确地说“将本地分支'master'推送到名为'origin'的远程”。这没有定义持久关系,它只执行一次这样的推送。请注意,假定远程分支被命名为“master”。
git push -u origin master
是相同的,除了它首先在本地分支“master”和名为“origin”的远程之间添加持久跟踪关系。和以前一样,假设远程分支被命名为“master”。
如果您已经使用-u
进行了推送,那么已经定义了该关系。将来,您可以简单地说git push
或git pull
,git会自动使用已定义的远程跟踪分支,而不会被明确告知。
您可以使用git branch -vv
查看跟踪关系,这将列出您的本地分支及其当前的HEAD提交,如果已设置,还会列出远程跟踪分支。这是一个例子。
$ git branch -vv
* master 58a0d68 [origin/master] Fix CSS regression bug
migration_tool 2a24ff7 [origin/migration_tool] [#906] Fix table layout problem
topic-ajax-timeouts fe854f2 Adjust timeouts to be more realistic
这里显示了3个分支及其当前的HEAD提交和提交消息。在前两个,指定了跟踪分支,但第三个分支没有跟踪远程分支。
答案 2 :(得分:5)
“跟踪”和“上游”是相关术语。 “跟踪”表示将本地存储库的分支与上游分支相关联,即位于远程存储库中的分支。例如,
git push -u origin newbranch
设置本地newbranch
的跟踪信息,以便生活在远程仓库中的newbranch
称为origin
(即您的本地仓库在昵称下知道的远程仓库{ {1}})被认为是您本地origin
的上游分支...并执行推送。
如果您通过克隆来获取本地存储库,则无需运行
newbranch
因为git push -u origin master
已经设置为origin/master
的上游分支。换句话说,master
已设置为跟踪master
。