Appearance
远程
Git 远程仓库-1. Git Clone
命令详解
从技术上来讲,git clone 命令在真实的环境下的作用是在本地创建一个远程仓库的拷贝(比如从 github.com)。
练习题答案:
bash
git clone
Git 远程仓库-2. 远程分支
远程分支
在 git clone 命令之后在我们的本地仓库多了一个名为 o/main 的分支, 这种类型的分支就叫 远程分支。
远程分支反映了远程仓库(在你上次和它通信时)的状态。
远程分支有一个特别的属性,在你切换到远程分支时,自动进入分离 HEAD 状态。
Git 这么做是出于不能直接在这些分支上进行操作的原因, 你必须在别的地方完成你的工作。
为什么有o/ ?
远程分支有一个命名规范 —— 它们的格式是:
<remote name>/<branch name>
。一个名为
o/main
的分支,那么这个分支就叫main
,远程仓库的名称就是o
。大多数的开发人员会将它们主要的远程仓库命名为
origin
,并不是o
。这是因为当你用 git clone 某个仓库时,Git 已经帮你把远程仓库的名称设置为origin
了。
练习题答案:
bash
git commit
git checkout o/main
git commit
Git 远程仓库-3. Git Fetch
命令详解
git fetch
- git fetch 实际上将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态。
- git fetch 通常通过互联网(使用
http://
或git://
协议) 与远程仓库通信。
git fetch做了什么?
git fetch 完成了仅有的但是很重要的两步:
- 从远程仓库下载本地仓库中缺失的提交记录
- 更新远程分支指针(如
o/main
)
git fetch 不会做的事
git fetch 并不会改变你本地仓库的状态。它不会更新你的 main
分支,也不会修改你磁盘上的文件。
练习题答案:
bash
git fetch
Git 远程仓库-4. Git Pull
命令详解
实际上,由于先抓取更新再合并到本地分支这个流程很常用,因此 Git 提供了一个专门的命令 git pull 来完成这两个操作。
git fetch + git merge o/main = git pull
练习题答案:
bash
git pull
Git 远程仓库-5. 模拟团队合作
练习题答案:
bash
git clone
git fakeTeamwork 2
git commit
git pull
Git 远程仓库-6. Git Push
命令详解
git push 负责将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录。
注意
git push 不带任何参数时的行为与 Git 的一个名为 push.default 的配置有关。
它的默认值取决于你正使用的 Git 的版本,在你的项目中进行推送之前,最好检查一下这个配置。
练习题答案:
bash
Git commit
Git commit
Git push
Git 远程仓库-7. 偏离的提交历史
内容详解
历史偏离的案例
你克隆了仓库,然后开始开发某种功能,在你提交之前,同事改了同一个地方且已经合并到了 master 分支。这情况(历史偏离)有许多的不确定性,Git 是不会允许你 push 变更的。它会强制你先合并远程最新的代码,然后才能 push。
解决这个问题最直接的方法就是通过 rebase 调整你的工作。
git fetch
更新了本地仓库中的远程分支git rebase o/main
或者git merge o/main
将我们的工作移动到最新的提交记录下git push
推送到远程仓库
简写:
git pull —rebase + git push
Orgit pull + git push
练习题答案:
base
Git clone
Git fakeTeamwork
Git commit
Git pull —rebase
Git push
Git 远程仓库-8. 锁定的Main(Locked Main)
内容详解
远程服务器拒绝!(Remote Rejected)
如果你是在一个大的合作团队中工作,很可能是main被锁定了,需要一些Pull Request流程来合并修改。
解决办法
- 新建一个分支feature,推送到远程服务器。
- 然后reset你的main分支和远程服务器保持一致,否则下次你pull并且他人的提交和你冲突的时候就会有问题。
练习题答案:
bash
# 5步答案
git checkout -b feature
git push
git checkout main
git reset HEAD^
git checkout feature
# 3步答案
git checkout -b feature
git push
git branch -f main o/main
Git 远程仓库高级操作-1. 推送主分支
内容详解
合并特性分支 :在大型项目中开发人员通常会在(从 main 上分出来的)特性分支上工作,工作完成后只做一次集成。有些开发人员只在 main 上做 push、pull —— 这样的话 main 总是最新的,始终与远程分支 (o/main) 保持一致。
练习题答案:
bash
git fetch
git rebase o/main side1
git rebase side1 side2
git rebase side2 side3
git rebase side3 main
Git 远程仓库高级操作-2. 合并远程仓库
内容详解
具体用merge还是rebase?
为了 push 新变更到远程仓库,你要做的就是包含远程仓库中最新变更。意思就是只要你的本地分支包含了远程分支(如 o/main)中的最新变更就可以了,至于具体是用 rebase 还是 merge,并没有限制。
rebase 的优缺点:
- 优点: Rebase 使你的提交树变得很干净, 所有的提交都在一条线上
- 缺点: Rebase 修改了提交树的历史
关于 merge 还是 rebase,仁者见仁,智者见智。
练习题答案:
bash
git checkout main
git pull
git merge side1
git merge side2
git merge side3
git push
Git 远程仓库高级操作-3. 远程追踪
内容详解
远程跟踪分支
这种关联在以下两种情况下可以清楚地得到展示:
- pull 操作时, 提交记录会被先下载到 o/main 上,之后再合并到本地的 main 分支。
- push 操作时, 我们把工作从 main 推到远程仓库中的 main 分支(同时会更新远程分支 o/main) 。
main 和 o/main 的关联关系就是由分支的“remote tracking”属性决定的。
- main 被设定为跟踪 o/main —— 这意味着为 main 分支指定了推送的目的地以及拉取后合并的目标。
- 当你克隆仓库时, Git 会为远程仓库中的每个分支在本地仓库中创建一个远程分支(比如 o/main)。
- 然后再创建一个跟踪远程仓库中活动分支的本地分支,默认情况下这个本地分支会被命名为 main。
- 克隆完成后,你会得到一个本地分支。
这也解释了为什么会在克隆的时候会看到下面的输出: local branch "main" set to track remote branch "o/main"
我能自己指定这个属性吗?
当然可以,你可以让任意分支跟踪 o/main, 然后该分支会像 main 分支一样得到隐含的 push 目的地以及 merge 的目标。
这意味着你可以在分支 totallyNotMain 上执行 git push,将工作推送到远程仓库的 main 分支上。
有两种方法设置这个属性:
第一种方法:就是通过远程分支切换到一个新的分支,执行:
git checkout -b totallyNotMain o/main
就可以创建一个名为 totallyNotMain 的分支,它跟踪远程分支 o/main。
第二种方法:设置远程追踪分支的方法,就是使用:git branch -u
命令,执行:
git branch -u o/main foo
这样 foo 就会跟踪 o/main 了。如果当前就在 foo 分支上, 还可以省略 foo:
git branch -u o/main
练习题答案:
bash
git checkout branch side o/main
git commit
git pull —rebase
git push
Git 远程仓库高级操作-4. Git push 的参数
git push添加参数
我们可以为 push 指定参数,语法是:git push <remote> <place>
这个命令是: git push origin main
翻译就是:
- 切到本地仓库中的“main”分支,获取所有的提交。
- 到远程仓库“origin”中找到“main”分支,将远程仓库中没有的提交记录都添加上去。
我们通过“place”参数来告诉 Git 提交记录来自于 main, 要推送到远程仓库中的 main。它实际就是要同步的两个仓库的位置。
PS: 需要注意的是:git checkout C0
+ git push origin main
不加参数会报错。
练习题答案:
bash
git push origin main
git push origin foo
Git 远程仓库高级操作-5. Git push 参数 2
<place>
参数详解
如果来源和去向分支的名称不同怎么办?
要同时为源和目的地指定 <place>
的话,只需要用冒号 :
将二者连起来就可以了:
git push origin <source>:<destination>
这个参数实际的值是个 refspec,“refspec” 是一个自造的词,意思是 Git 能识别的位置(比如分支 foo 或者 HEAD~1),例如:
git push origin foo^:main
如果你要推送到的目的分支不存在会怎么样呢?
Git 会在远程仓库中根据你提供的名称帮你创建这个分支!
git push origin main:newBranch
练习题答案:
bash
git push origin foo:main
git push origin main^:foo
Git 远程仓库高级操作-6. Git fetch 的参数
内容详解
git fetch 的参数
和 git push 极其相似。他们的概念是相同的,只是方向相反罢了 <source>:<destination>
。
- source 现在指的是远程仓库中的位置。
<destination>
才是要放置提交的本地仓库的位置。
我在这里介绍它主要是为了从概念上说明 fetch 和 push 的相似性,只是方向相反罢了。
git fetch origin C2:bar
如果执行命令前目标分支不存在会怎样呢?
跟 git push 一样,Git 会在 fetch 前自己创建立本地分支。
没有参数呢?
如果 git fetch 没有参数,它会下载所有的提交记录到各个远程分支。
练习题答案:
bash
git fetch origin C3:foo
git fetch origin C6:main
git checkout foo
git merge C6
Git 远程仓库高级操作-7. 没有 source 的 source
古怪的 <source>
Git 有两种关于 <source>
的用法是比较诡异的,即你可以在 git push 或 git fetch 时不指定任何 source。
git push origin :side
: 如果 push 空到远程仓库,它 会删除远程仓库中的分支 。git fetch origin :bugFix
:如果 fetch 空 到本地,会 会在本地创建一个新分支 。
练习题答案:
bash
git push origin :foo
git fetch origin :bar
Git 远程仓库高级操作-8. Git pull 的参数
Git pull 参数
git pull 实际上就是 fetch + merge 的缩写, git pull 唯一关注的是提交最终合并到哪里(也就是为 git fetch 所提供的 destination 参数)
以下命令在 Git 中是等效的:
git pull origin foo
相当于:git fetch origin foo; git merge o/foo
还有...
git pull origin bar:bugFix
相当于:git fetch origin bar:bugFix; git merge bugFix
练习题答案:
bash
git pull origin c3:foo
git pull origin c2:side