Learn Git Branching:在游戏中学会Git
Learn Git Branching是一个学习Git操作的教程,作者为不同的命令设计了相应的关卡,它并不枯燥乏味,相反,我们每通过一个关卡,自信心就会提升,兴趣也会加深,带着满满的成就感去学习,真的很有趣!考虑到自我思考的重要性,作者将相关隐藏命令陆续放在了后面的关卡中,不至于让玩家一开始就急于看答案,而且配上优雅的动图,看起来真的舒心。作者考虑真的很周到,必须点个赞~
每个关卡的答案不唯一,只要发挥你的想象达到目标即可。下面是我的关卡挑战合集。
快去玩转Git吧!(https://learngitbranching.js.org)
链接💨💨💨Learn Git Branching
基础篇
1?? git commit
git commit
2?? git branch
git branch 分支名 创建分支
git checkout 分支名 切换分支,即将HEAD 移动到分支上
创建并移动到分支上:
git branch bugFix
git checkout bugFix
---
git checkout -b bugFix
3?? git merge
git merge 合并分支
git checkout -b bugFix
git commit
git checkout main
git commit
git merge bugFix
4?? git rebase
合并分支并返回主线
git checkout -b bugFix
git commit
git checkout main
git commit
git checkout bugFix
git rebase main
高级篇
1?? 分离 HEAD
HEAD 总是指向当前分支上最近一次提交记录,大多数修改提交树的 Git 命令都是从改变HEAD 的指向开始的,HEAD 通常情况下是指向分支名的(如 bugFix)。
分离的 HEAD 就是让其指向了某个具体的提交记录而不是分支名。
查看HEAD指向 cat .git/HEAD
指向引用 git symbolio-ref HEAD
------------------------------
git checkout C4
2?? 相对引用(^)
git log 查看提交记录的哈希值(基于SHA-1,共40位),仅输入前几个字符即可。
- 使用
^ 向上移动1个提交记录,把^ 加到引用名称的后面,表示让git 寻找指定提交记录的父提交,比如切换到main 的父节点 git checkout main^ - 使用
~<num> 向上移动多个记录,如 ~3 ,完整如 git checkout main~3
git checkout bugFix
git checkout C4
git checkout HEAD^
---
git checkout C4^
---
git checkout C4~1
3?? 相对引用(~)
- 使用
~<num> 向上移动多个记录,如 ~3 ,完整如 git checkout HEAD~3
强行修改分支位置
git branch -f main C6
git checkout HEAD^
git branch -f bugFix HEAD~1
4?? 撤销变更
git reset HEAD^
git checkout pushed
git revert HEAD
移动提交记录
1?? git cherry-pick
git cherry-pick <...> ,如果想将一些提交复制到当前所在的位置(HEAD )下面的话,该命令非常实用,如git cherry-pick C2 C4 是将C2和C4分支 复制到当前位置
git cherry-pick C3 C4 C7
2?? 交互式rebase
git rebase -i HEAD~4 (pick C4 并 移动顺序)
杂项
1?? 只做一个提交记录
git rebase -i git cherry-pick
git rebase -i HEAD~3
git checkout main
git rebase bugFix
--
git rebase -i HEAD~3
git branch -f main HEAD
2?? 提交的技巧#1
- 在
newImage 分支上进行了一次提交,基于它又创建了option分支,然后又提交了一次。现在我们想修改newImage 中的内容
- 使用
git rebase -i 将提交重排 - 使用
git commit --amend 进行小修改 - 再使用
git rebase -i 移动到原来的顺序 - 将
main 移动到HEAD
git rebase -i HEAD~2
git rebase -i HEAD
git rebase -i HEAD~2
git branch -f main HEAD
3?? 提交的技巧#2
cherry-pick 可以将提交树上任何地方的提交记录取过来追加到HEAD 上(只要不是HEAD 上游的提交就没问题)
git checkout C1
git cherry-pick C2
git checkout C1
git cherry-pick C2 C3
git branch -f main HEAD
---
git checkout C1
git cherry-pick C2
git checkout main
git cherry-pick C2 C3
4?? git tag
git tag v0 C1
git tag v1 C2
git checkout v1
5?? git describe
git describe C5
git commit
高级话题
1?? 多次rebase
git checkout bugFix
git rebase main
git checkout side
git rebase bugFix
git checkout another
git rebase -i side
git branch -f main HEAD
---
git rebase main bugFix
git rebase bugFix side
git rebase side another
git rebase another main
2?? 两个父节点
^ 后面也可以跟数字,表示指定合并提交记录的某个父提交(一个以上的父分支),如 git checkout main^2 - 操作符
~ 和^ 支持链式操作,如git checkout HEAD~^2~2
git checkout main~1^2^
git branch bugWork
git checkout main
---
(分支不存在会主动创建)
git branch -f bugWork main^^2^
3?? 纠缠不清的分支
git checkout one
git cherry-pick C4 C3 C2
git checkout two
git cherry-pick C5 C4 C3 C2
git branch -f three C2
Push & Pull —— Git 远程仓库
1?? git clone
远程仓库的特点:
git clone 在本地创建一个远程仓库的克隆
git clone
2?? 远程分支
- 远程仓库名一般设置为
origin ,且git 默认将远程仓库设置为origin - 路径
<remote name>/<branch name> ,如o/main ,origin/main
git commit
git checkout o/main
git commit
3?? git fetch
git fetch 从远程仓库获取更新的分支,主要做了两步
- 从远程仓库下载本地仓库中缺失的提交记录
- 更新远程分支(如
origin/main )
git fetch 实际上将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态。远程分支反映了远程仓库在你最后一次与它通信时的状态,git fetch 就是你与远程仓库通信的方。git fetch 通常通过互联网(使用 http:// 或 git:// 协议) 与远程仓库通信。
==git fetch 并不会改变本地仓库的状态,也不会更新main 分支,也不会修改磁盘上的文件。==所以可以将git fetch 理解为单纯的下载操作。
git fetch
4?? git pull
git pull 抓取更新并合并到本地分支git fetch ; git merge orign/main 等价于git pull
git fetch
git merge o/main
---
git pull
5?? 模拟团队合作
git clone
git fakeTeamwork main 2
git fetch
git commit
git merge o/main
---
git clone
git fakeTeamwork main 2
git commit
git pull
6?? git push
git push 负责将你的变更上传到指定的远程仓库- 注意——
git push 不带任何参数时的行为与 Git 的一个名为 push.default 的配置有关。它的默认值取决于你正使用的 Git 的版本。
git commit
git commit
git push
7?? 偏离的提交历史
假如你克隆了一个仓库,研发某个新功能完毕准备提交时,发现你的同事更新了好多分支并且已经推送到远程仓库了,因此你的工作就变成了基于项目旧版的代码,与远程仓库最新的代码不匹配了。
解决办法:调整你的工作使你的工作基于最新的远程分支
-
使用git fetch 更新本地仓库中的远程分支,然后用rebase 将我们的工作移动到最新的提交记录下 git fetch; git rebase o/main 等价于git pull --rebase -
更新本地仓库中的远程分支,然后合并新变更到我们的本地分支 git fetch; git merge o/main 等价于git pull
git clone
git fakeTeamwork main
git commit
git fetch
git rebase o/main
git push
--
git clone
git fakeTeamwork main
git commit
git fetch
git merge o/main
git push
---
git clone
git fakeTeamwork main
git commit
git pull --rebase
git push
---
git clone
git fakeTeamwork main
git commit
git pull
git push
8?? 锁定的main(locked main)
main 被锁定时需要一些pull request 流程来合并修改。
新建一个分支feature ,推送到远程服务器。然后reset 你的main分支和远程服务器保持一致,否则下次你pull 并且他人的提交和你冲突的时候就会有问题。
git branch feature
git branch -f main o/main
git checkout feature
git push
---
git branch -f main o/main
git branch -f feature C2
git checkout feature
git push
---
git checkout -b feature
git branch -f main o/main
git push
---
show solution
(在本程序中默认的行为是 --hard 硬重置,可以尽情省略掉那个选项以避免麻烦!但是要记录 Git 中默认的是 --mixed)
git reset --hard o/main
git checkout -b feature C2
git push origin feature
关于 origin 和它的周边 —— Git 远程仓库高级操作
1?? 推送主分支
git checkout main
git pull --rebase
git rebase main side1
git rebase HEAD side2
git rebase HEAD side3
git branch -f main side3
git checkout main
git push
---
git fetch
git rebase o/main side1
git rebase side1 side2
git rebase side2 side3
git rebase side3 main
git push
2?? 合并远程分支
- 为了 push 新变更到远程仓库,你要做的就是包含远程仓库中最新变更。意思就是只要你的本地分支包含了远程分支(如
o/main )中的最新变更就可以了,至于具体是用 rebase 还是 merge,并没有限制
rebase 的优点是使你的提交树变得很干净,所有的提交都在一条线上,缺点是修改了树的提交历史。
git fetch
git branch -f main o/main
git checkout main
git merge side1
git merge side2
git merge side3
git push
---
git fetch
git rebase o/main main
git merge side1
git merge side2
git merge side3
git push
---
git checkout main
git pull
git merge side1
git merge side2
git merge side3
git push
3?? 远程追踪
pull 操作时, 提交记录会被先下载到 o/main 上,之后再合并到本地的 main 分支。隐含的合并目标由这个关联确定的。push 操作时, 我们把工作从 main 推到远程仓库中的 main 分支(同时会更新远程分支 o/main ) 。
main 和 o/main 的关联关系就是由分支的“remote tracking”属性决定的。main 被设定为跟踪 o/main —— 这意味着为 main 分支指定了推送的目的地以及拉取后合并的目标。当你克隆时, Git 会为远程仓库中的每个分支在本地仓库中创建一个远程分支(比如 o/main )。然后再创建一个跟踪远程仓库中活动分支的本地分支,默认情况下这个本地分支会被命名为 main 。克隆完成后,你会得到一个本地分支(如果没有这个本地分支的话,你的目录就是“空白”的)。
我们可以让任意分支跟踪 o/main , 然后该分支会像 main 分支一样得到隐含的 push 目的地以及 merge 的目标。 这意味着可以在分支 totallyNotMain 上执行 git push ,将工作推送到远程仓库的 main 分支上。
创建名为totallyNotMain的分支,来跟踪远程分支o/main ,有两证方式可实现:
git checkout -b totallyNotMain o/main git branch -u o/main totallyNotMain
git checkout -b side o/main
git commit
git pull --rebase
git push
4?? git push的参数
为git push 指定参数,语法为git push <remote> <place>
例如git push origin main 的意思是:切换到本地仓库中的main 分支,获取所有的提交,再到远程仓库origin 中找到main 分支,将远程仓库中没有的提交都添加上去。
git push origin main
git push origin foo
5?? git push的参数2
git push origin <source>:<destination> 是将本地source 分支推送到远程destination 分支。并且source 是git 可识别的位置,如name~3 、name^ ,name^2 等。如果推送的目的分支不存在git 会在远程仓库中自动创建这个分支。
git push origin foo:main
git push origin main^:foo
6?? git fetch的参数
git fetch 同样具有参数,只是方向相反,例如命令git fetch origin foo 会到远程仓库foo 分支上,获取本地不存在的提交,放到本地的o/foo 上。
- 如果
git fetch 没有参数,它会下载所有的提交记录到各个远程分支
git fetch origin main~:foo
git fetch origin foo:main
git checkout foo
git merge main
7?? 没有source的source
git 有两种关于 <source> 的用法是比较诡异的,即你可以在 git push 或 git fetch 时不指定任何 source ,方法就是仅保留冒号和 destination 部分,source 部分留空。
git push origin :foo 操作是删除远程分支foo git fetch origin :bar 操作是创建本地分支bar
git push origin :foo
git fetch origin :bar
8?? git pull的参数
git pull 即git fetch 和git merge 的缩写。
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
git pull origin bar:foo
git pull origin main:side
恭喜通关!!!
|