Learn Git Branching是一个学习Git操作的教程,作者为不同的命令设计了相应的关卡,它并不枯燥乏味,相反,我们每通过一个关卡,自信心就会提升,兴趣也会加深,带着满满的成就感去学习,真的很有趣!考虑到自我思考的重要性,作者将相关隐藏命令陆续放在了后面的关卡中,不至于让玩家一开始就急于看答案,而且配上优雅的动图,看起来真的舒心。作者考虑真的很周到,必须点个赞~
每个关卡的答案不唯一,只要发挥你的想象达到目标即可。下面是我的关卡挑战合集。
快去玩转Git吧!(https://learngitbranching.js.org)
链接Learn Git Branching
文章目录- Learn Git Branching:在游戏中学会Git
- 基础篇
- 1️⃣ git commit
- 2️⃣ git branch
- 3️⃣ git merge
- 4️⃣ git rebase
- 高级篇
- 1️⃣ 分离 HEAD
- 2️⃣ 相对引用(^)
- 3️⃣ 相对引用(~)
- 4️⃣ 撤销变更
- 移动提交记录
- 1️⃣ git cherry-pick
- 2️⃣ 交互式rebase
- 杂项
- 1️⃣ 只做一个提交记录
- 2️⃣ 提交的技巧#1
- 3️⃣ 提交的技巧#2
- 4️⃣ git tag
- 5️⃣ git describe
- 高级话题
- 1️⃣ 多次rebase
- 2️⃣ 两个父节点
- 3️⃣ 纠缠不清的分支
- Push & Pull —— Git 远程仓库
- 1️⃣ git clone
- 2️⃣ 远程分支
- 3️⃣ git fetch
- 4️⃣ git pull
- 5️⃣ 模拟团队合作
- 6️⃣ git push
- 7️⃣ 偏离的提交历史
- 8️⃣ 锁定的main(locked main)
- 关于 origin 和它的周边 —— Git 远程仓库高级操作
- 1️⃣ 推送主分支
- 2️⃣ 合并远程分支
- 3️⃣ 远程追踪
- 4️⃣ git push的参数
- 5️⃣ git push的参数2
- 6️⃣ git fetch的参数
- 7️⃣ 没有source的source
- 8️⃣ git pull的参数
基础篇 1️⃣ git commit
git commit2️⃣ git branch
git branch 分支名 创建分支
git checkout 分支名 切换分支,即将HEAD移动到分支上
创建并移动到分支上:
git branch bugFix git checkout bugFix --- git checkout -b bugFix3️⃣ git merge
git merge 合并分支
git checkout -b bugFix git commit git checkout main git commit git merge bugFix4️⃣ 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 C42️⃣ 相对引用(^)
git log 查看提交记录的哈希值(基于SHA-1,共40位),仅输入前几个字符即可。
- 使用 ^ 向上移动1个提交记录,把^加到引用名称的后面,表示让git寻找指定提交记录的父提交,比如切换到main的父节点 git checkout main^
- 使用~
向上移动多个记录,如 ~3,完整如 git checkout main~3
git checkout bugFix git checkout C4 git checkout HEAD^ --- git checkout C4^ --- git checkout C4~13️⃣ 相对引用(~)
- 使用~
向上移动多个记录,如 ~3,完整如 git checkout HEAD~3
强行修改分支位置
-
使用 -f选项让分支指向另一个提交,
如git branch -f main HEAD~3,将main分支强制指向HEAD的第3级父提交
git branch -f main C6 git checkout HEAD^ git branch -f bugFix HEAD~14️⃣ 撤销变更
-
本地分支的撤销:git reset,通过把分支记录回退几个提交记录来实现撤销改动。
例如,git reset HEAD~1
-
远程分支的撤销:git revert,例如 git revert HEAD
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 C72️⃣ 交互式rebase
- git rebase -i HEAD~4
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 HEAD2️⃣ 提交的技巧#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 HEAD3️⃣ 提交的技巧#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 C34️⃣ git tag
-
标签tag在代码库中起着锚点的作用
-
git tag v1 C1创建一个指向C1的标签v1
git tag v0 C1 git tag v1 C2 git checkout v15️⃣ git describe
-
git describe 描述离当前(ref)最近的标签,
输出为
_ _g
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 main2️⃣ 两个父节点
- ^后面也可以跟数字,表示指定合并提交记录的某个父提交(一个以上的父分支),如 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 C2Push & Pull —— Git 远程仓库 1️⃣ git clone
远程仓库的特点:
- 数据备份
- 代码社交化(为项目做贡献)
git clone在本地创建一个远程仓库的克隆
git clone2️⃣ 远程分支
- 远程仓库名一般设置为origin,且git默认将远程仓库设置为origin
- 路径
/ ,如o/main,origin/main
git commit git checkout o/main git commit3️⃣ git fetch
git fetch从远程仓库获取更新的分支,主要做了两步
- 从远程仓库下载本地仓库中缺失的提交记录
- 更新远程分支(如origin/main)
git fetch 实际上将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态。远程分支反映了远程仓库在你最后一次与它通信时的状态,git fetch就是你与远程仓库通信的方。git fetch 通常通过互联网(使用 http:// 或 git:// 协议) 与远程仓库通信。
==git fetch并不会改变本地仓库的状态,也不会更新main分支,也不会修改磁盘上的文件。==所以可以将git fetch理解为单纯的下载操作。
git fetch4️⃣ git pull
- git pull抓取更新并合并到本地分支
- git fetch ; git merge orign/main等价于git pull
git fetch git merge o/main --- git pull5️⃣ 模拟团队合作
git clone git fakeTeamwork main 2 git fetch git commit git merge o/main --- git clone git fakeTeamwork main 2 git commit git pull6️⃣ git push
- git push负责将你的变更上传到指定的远程仓库
- 注意——git push 不带任何参数时的行为与 Git 的一个名为 push.default 的配置有关。它的默认值取决于你正使用的 Git 的版本。
git commit git commit git push7️⃣ 偏离的提交历史
假如你克隆了一个仓库,研发某个新功能完毕准备提交时,发现你的同事更新了好多分支并且已经推送到远程仓库了,因此你的工作就变成了基于项目旧版的代码,与远程仓库最新的代码不匹配了。
解决办法:调整你的工作使你的工作基于最新的远程分支
-
使用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 push8️⃣ 锁定的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 push2️⃣ 合并远程分支
- 为了 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 push3️⃣ 远程追踪
- 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 push4️⃣ git push的参数
为git push指定参数,语法为git push
例如git push origin main的意思是:切换到本地仓库中的main分支,获取所有的提交,再到远程仓库origin中找到main分支,将远程仓库中没有的提交都添加上去。
git push origin main git push origin foo5️⃣ git push的参数2
git push origin
git push origin foo:main git push origin main^:foo6️⃣ 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 main7️⃣ 没有source的source
git 有两种关于
- git push origin :foo 操作是删除远程分支foo
- git fetch origin :bar操作是创建本地分支bar
git push origin :foo git fetch origin :bar8️⃣ 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
恭喜通关!!!



