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