版本控制-git-LearnGitBranching-远程
本文来源于LearnGitBranching官网
Push & Pull —— Git 远程仓库!
远程仓库
远程仓库有一系列强大的特性
- 首先也是最重要的的点, 远程仓库是一个强大的备份。本地仓库也有恢复文件到指定版本的能力, 但所有的信息都是保存在本地的。有了远程仓库以后,即使丢失了本地所有数据, 你仍可以通过远程仓库拿回你丢失的数据。
- 还有就是, 远程让代码社交化了! 既然你的项目被托管到别的地方了, 你的朋友可以更容易地为你的项目做贡献(或者拉取最新的变更)
现在用网站来对远程仓库进行可视化操作变得越发流行了(像 GitHub), 但远程仓库永远是这些工具的顶梁柱, 因此理解其概念非常的重要!
我们创建远程仓库的命令
git clone
远程分支
远程分支反映了远程仓库(在你上次和它通信时)的状态
远程分支有一个特别的属性,在你检出时自动进入分离 HEAD 状态。Git 这么做是出于不能直接在这些分支上进行操作的原因, 你必须在别的地方完成你的工作, (更新了远程分支之后)再用远程分享你的工作成果
远程分支命名规范:<remote name>/<branch name>
大多数的开发人员会将它们主要的远程仓库命名为 origin,并不是 o。这是因为当你用 git clone 某个仓库时,Git 已经帮你把远程仓库的名称设置为 origin 了
Git Fetch
从远程仓库获取数据 git fetch。
从远程仓库获取数据时, 远程分支也会更新以反映最新的远程仓库。
git fetch 做了些什么
git fetch 完成了两步:
- 从远程仓库下载本地仓库中缺失的提交记录
- 更新远程分支指针(如 o/main)
git fetch 将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态。
git fetch 通常通过互联网(使用 http:// 或 git:// 协议) 与远程仓库通信。
git fetch 不会做的事
git fetch 并不会改变你本地仓库的状态。它不会更新你的 main 分支,也不会修改你磁盘上的文件。
Git Pull
当远程分支中有新的提交时,你可以像合并本地分支那样来合并远程分支:
- git cherry-pick o/main
- git rebase o/main
- git merge o/main
- …
git pull 就是 git fetch 和 git merge 的缩写
模拟团队合作
Git Push
git push 负责将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录
git push 不带任何参数时的行为与 Git 的一个名为 push.default 的配置有关。它的默认值取决于你正使用的 Git 的版本,但是在教程中我们使用的是 upstream
push之前如果和远程仓库的分支冲突,则会被拒绝,所以在push之前最好先执行pull或者pull –rebase
大型团队合作
每个人维护自己的分支,另外专门由一个人来检查大家的分支并合并分支
关于 origin 和它的周边 —— Git 远程仓库高级操作
合并特性分支
团队开发工作流:
- 将特性分支集成到 main 上
- 推送并更新远程分支
让我们看看如何快速的更新 main 分支并推送到远程。
|
|
我们执行了两个命令:
- 将我们的工作 rebase 到远程分支的最新提交记录
- 向远程仓库推送我们的工作
为什么不用 merge 呢?
只要你的本地分支包含了远程分支(如 o/main)中的最新变更就可以了,至于具体是用 rebase 还是 merge,并没有限制。
在开发社区里,有许多关于 merge 与 rebase 的讨论。以下是关于 rebase 的优缺点:
优点:Rebase 使你的提交树变得很干净, 所有的提交都在一条线上
缺点:Rebase 修改了提交树的历史
比如, 提交 C1 可以被 rebase 到 C3 之后。这看起来 C1 中的工作是在 C3 之后进行的,但实际上是在 C3 之前。
一些开发人员喜欢保留提交历史,因此更偏爱 merge。而其他人可能更喜欢干净的提交树,于是偏爱 rebase。仁者见仁,智者见智。 :D
远程跟踪分支
- pull 操作时, 提交记录会被先下载到 o/main 上,之后再合并到本地的 main 分支。隐含的合并目标由这个关联确定的。
- push 操作时, 我们把工作从 main 推到远程仓库中的 main 分支(同时会更新远程分支 o/main) 。这个推送的目的地也是由这种关联确定的!
远程跟踪
直接了当地讲,main 和 o/main 的关联关系就是由分支的“remote tracking”属性决定的。main 被设定为跟踪 o/main —— 这意味着为 main 分支指定了推送的目的地以及拉取后合并的目标。
当你克隆仓库的时候, Git 就自动帮你把这个属性设置好了。
当你克隆时, Git 会为远程仓库中的每个分支在本地仓库中创建一个远程分支(比如 o/main)。然后再创建一个跟踪远程仓库中活动分支的本地分支,默认情况下这个本地分支会被命名为 main。
克隆完成后,你会得到一个本地分支(如果没有这个本地分支的话,你的目录就是“空白”的),但是可以查看远程仓库中所有的分支(如果你好奇心很强的话)。这样做对于本地仓库和远程仓库来说,都是最佳选择。
这也解释了为什么会在克隆的时候会看到下面的输出:
|
|
我能自己指定这个属性吗?
有两种方法设置这个属性,第一种就是通过远程分支检出一个新的分支,执行:
|
|
就可以创建一个名为 totallyNotMain 的分支,它跟踪远程分支 o/main。
第二种方法
另一种设置远程追踪分支的方法就是使用:git branch -u 命令,执行:
|
|
这样 foo 就会跟踪 o/main 了。如果当前就在 foo 分支上, 还可以省略 foo:
|
|
Git Push 的参数
|
|
|
|
我们通过“place”参数来告诉 Git 提交记录来自于 main, 要推送到远程仓库中的 main
需要注意的是,因为我们通过指定参数告诉了 Git 所有它需要的信息, 所以它就忽略了我们所检出的分支的属性
参数详解
如果来源和去向分支的名称不同呢?比如你想把本地的 foo 分支推送到远程仓库中的 bar 分支。
要同时为源和目的地指定 <place>
的话,只需要用冒号 : 将二者连起来就可以了:
|
|
source 可以是任何 Git 能识别的位置:
如果你要推送到的目的分支不存在,Git 会在远程仓库中根据你提供的名称帮你创建这个分支!
Git fetch 的参数
参数
|
|
Git 会到远程仓库的 foo 分支上,然后获取所有本地不存在的提交,放到本地的 o/foo 上,但是不会覆盖本地foo分支。
Git 做了一些特殊处理,因为你可能在 foo 分支上的工作还未完成,你也不想弄乱它。 git fetch 不会更新本地的非远程分支, 只是下载提交记录(这样, 你就可以对远程分支进行检出或者合并了)。
<source>
:<destination>
:source 现在指的是远程仓库中的位置,而 <destination>
才是要放置提交的本地仓库的位置。它与 git push 刚好相反
理论上虽然行的通,但开发人员很少这么做。
来看个疯狂的例子:
|
|
跟 git push 一样,Git 会在 fetch 前自己创建立本地分支, 就像是 Git 在 push 时,如果远程仓库中不存在目标分支,会自己在建立一样
如果 git fetch 没有参数,它会下载所有的提交记录到各个远程分支
古怪的
在 git push 或 git fetch 时不指定任何 source
- git push origin :side
- git fetch origin :bugFix
push 空 到远程仓库会删除远程仓库中的分支
如果 fetch 空 到本地,会在本地创建一个新分支。
Git pull 参数
git pull 就是 fetch 后跟 merge 的缩写,可以使用–rebase选项选择rebase而不是merge
以下命令在 Git 中是等效的:
git pull origin foo
:git fetch origin foo; git merge o/foo
git pull origin bar~1:bugFix
:git fetch origin bar~1:bugFix; git merge bugFix
如果我们指定要抓取的 place,所有的事情都会跟之前一样发生,只是增加了 merge 操作
pull 也可以用 source:destination 吗? 当然喽, 看看吧: