本文有点长而且有点乱,但就像Mark Twain Blaise Pascal的笑话里说的那样:我没有时间让它更短些。在Git的邮件列表里有很多关于本文的讨论,我会尽量把其中相关的观点列在下面。 我最常说的关于git使用的一个经验就是:
git 将下载(fetch)和合并(merge)放到一个命令里的另外一个弊端是,你的本地工作目录在未经确认的情况下就会被远程分支更新。当然,除非你关闭所 |
Andy
|
分支(Branches) 在说git pull之前,我们需要先澄清分支的概念(branches)。很多人像写代码似的用一行话来描述分支是什么,例如:
我认为你应该这样来理解分支的概念:它是用来标记特定的代码提交,每一个分支通过SHA1sum值来标识,所以对分支进行的操作是轻量级的--你改变的仅仅是SHA1sum值。 |
Andy
|
这个定义或许会有意想不到的影响。比如,假设你有两个分支,“stable” 和 “new-idea”, 它们的顶端在版本 E 和 F: A-----C----E ("stable") B-----D-----F ("new-idea") 所以提交(commits) A, C和 E 属于“stable”,而 A, B, D 和 F 属于 “new-idea”。如果之后你用下面的命令 将“new-idea” merge 到 “stable” : git checkout stable # Change to work on the branch "stable" git merge new-idea # Merge in "new-idea" …那么你会得到这个: A-----C----E----G ("stable") \ / B-----D-----F ("new-idea") 要是你继续在“new idea” 和“stable”分支提交, 会得到: A-----C----E----G---H ("stable") \ / B-----D-----F----I ("new-idea") 因此现在A, B, C, D, E, F, G 和 H 属于 “stable”,而A, B, D, F 和 I 属于 “new-idea”。 当然了,分支确实有些特殊的属性——其中最重要的是,如果你在一个分支进行作业并创建了一个新的提交(commits),该分支的顶端将前进到那个提交(commits)。这正是你所希望的。当用git merge 进行合并(merge)的时候,你只是指定了要合并到当前分支的那个并入分支,以及当前分支的当前进展。 |
super0555
|
另一个表明使用分支会有很大帮助的观点的常见情形是:假设你直接工作在一个项目的主要分支(称为“主版本”),当你意识到你所做的可能是一个坏主意时已经晚了,这时你肯定宁愿自己是工作在一个主题分支上。如果提交图看起来像这样: last version from another repository | v M---N-----O----P---Q ("master") 那么你把你的工作用下面的一组命令分开做(如图显示的是执行它们之后所更改的状态): git branch dubious-experiment M---N-----O----P---Q ("master" and "dubious-experiment") git checkout master # Be careful with this next command: make sure "git status" is # clean, you‘re definitely on "master" and the # "dubious-experiment" branch has the commits you were working # on first... git reset --hard <SHA1sum of commit N> ("master") M---N-------------O----P---Q ("dubious-experiment") git pull # Or something that updates "master" from # somewhere else... M--N----R---S ("master") O---P---Q ("dubious-experiment") 这是个看起来我最终做了很多的事情。 |
赵亮-碧海情天
|
分支类型 分支这个术语不太容易理解,而且在git的开发过程中发生了很多变化。但简单来说git的分支只有两种: a)“本地分支(local branches)” ,当你输入“git branch”时显示的。例如下面这个小例子: $ git branch debian server * master b)“远程跟踪分支(Remote-tracking branches)” ,当你输入“git branch -r”是显示的,如: $ git branch -r cognac/master fruitfly/server origin/albert origin/ant origin/contrib origin/cross-compile 从上面的输出可以看到,跟踪分支的名称前有一个“远程的”标记名称(如 |
Andy
|
如果你对分支在本地是如何存储感兴趣的话,看看下面文件:
两种类型的分支在某些方面十分相似-它们都只是在本地存储一个表示提交的SHA1校验和。(我强调“本地”,因为许多人看到"origin/master" 就认为这个分支在某种意义上说是不完整的,没有访问远端服务器的权限- 其实不是这种情况。) 不管如何相似,它们还是有一个特别重大的区别:
因此,你对远端跟踪分支最多能做的是下面事情中的一件:
|
几点人
|
基于远程跟踪分支创建本地分支如果你想基于远程跟踪分支创建本地分支(在本地分支上工作),你可以使用如下命令:git branch –track或git checkout –track -b,两个命令都可以让你切换到新创建的本地分支。例如你用git branch -r命令看到一个远程跟踪分支的名称为“origin/refactored”是你所需要的,你可以使用下面的命令: git checkout --track -b refactored origin/refactored 在上面的命令里,“refactored”是这个新分支的名称,“origin/refactored”则是现存远程跟踪分支的名称。(在git最新的版本里,例子中‘-track’选项已经不需要了,如果最后一个参数是远程跟踪分支,这个参数会被默认加上。) |
Andy
|
“–track”选项会设置一些变量,来保持本地分支和远程跟踪分支的相关性。他们对下面的情况很有用:
Your branch and the tracked remote branch ‘origin/master‘ have diverged, and respectively have 3 and 384 different commit(s) each. 或者: Your branch is behind the tracked remote branch ‘origin/master‘ by 3 commits, and can be fast-forwarded. 允许使用的配置变量是:“branch.<local-branch-name>.merge”和“branch.<local-branch-name>.remote”,但通常情况下你不用考虑他们的设置。 |
Andy
|
当从远程代码仓库创建一个本地分支之后,你会注意到,“git branch -r”能列出很多远程跟踪分支,但你的电脑上只有一个本地分支,你需要给上面的命令设置一个参数,来指定本地分支和远程分支的对应。
下面我们来看一个例子,如何从远程分支中更新本地代码,以及如何把本地分支推送到一个新的远程仓库中。 |
Andy
|
从远端仓库进行更新如果我想从远端的源仓库更新到本地的代码仓库,可以输入“git fetch origin”的命令,该命令的输入类似如下格式: remote: Counting objects: 382, done. remote: Compressing objects: 100% (203/203), done. remote: Total 278 (delta 177), reused 103 (delta 59) Receiving objects: 100% (278/278), 4.89 MiB | 539 KiB/s, done. Resolving deltas: 100% (177/177), completed with 40 local objects. From ssh://[email protected]/srv/git/fiji 3036acc..9eb5e40 debian-release-20081030 -> origin/debian-release-20081030 * [new branch] debian-release-20081112 -> origin/debian-release-20081112 * [new branch] debian-release-20081112.1 -> origin/debian-release-20081112.1 3d619e7..6260626 master -> origin/master 最重要的是这两行: 3036acc..9eb5e40 debian-release-20081030 -> origin/debian-release-20081030 * [new branch] debian-release-20081112 -> origin/debian-release-20081112 第一行表明远端的origin/debian-release-20081030分支的提交(commit)ID已经从3036acc更新为 |
Andy
|
前面那些行显示出“git fetch”命令会将哪些文件下载到本地,这些文件一旦下载到本地之后,就可以在本地进行任意操作了。 “git git merge origin/master ( |
Andy
|
如果你只是想看看本地分支和远程分支的差异,你可以使用下面的命令: git diff master origin/master 单独进行下载和合并是一个好的做法,你可以先看看下载的是什么,然后再决定是否和本地代码合并。而且分开来做,可以清晰的区别开本地分支和远程分支,方便选择使用。 |
Andy
|
把你的变更推送到一个远程仓库如何通过其他的方式呢? 假设你对 “experimental”分支做了变更并且希望把他push到"origin"远程仓库中去. 你可以这样做:
你可能将会收到:远程仓库无法fast-forward该分支的错误信息, 这将意味着可能有别人push了不同的变更到了这个分支上.所以,你需要fetch和merge别人的变更并再次尝试push操作. |
_Raymond
|
git push的操作不会牵扯远程跟踪分支(origin/experimental),只有在你下次进行git fetch时才会被更新。 上面这个说法不对,根据Deskin Miller的评论纠正:当推送到对应的远程分支后,你的远程跟踪分支就会被更新。 |