Learn Git Branching:在游戏中学会Git

Posted 白鳯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Learn Git Branching:在游戏中学会Git相关的知识,希望对你有一定的参考价值。

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

强行修改分支位置

  • 使用 -f选项让分支指向另一个提交

    git branch -f main HEAD~3,将main分支强制指向HEAD的第3级父提交

git branch -f main C6
git checkout HEAD^
git branch -f bugFix HEAD~1

4️⃣ 撤销变更

  • 本地分支的撤销: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 C7

2️⃣ 交互式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 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

  • 标签tag在代码库中起着锚点的作用

  • git tag v1 C1创建一个指向C1的标签v1

git tag v0 C1
git tag v1 C2
git checkout v1

5️⃣ git describe

  • git describe <ref>描述离当前(ref)最近的标签,

    输出为 <tag>_<numCommits>_g<hash>

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/mainorigin/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) 。

maino/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分支。并且sourcegit可识别的位置,如name~3name^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 pushgit 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 pullgit fetchgit 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

恭喜通关!!!

以上是关于Learn Git Branching:在游戏中学会Git的主要内容,如果未能解决你的问题,请参考以下文章

Learn Git Branching:在游戏中学会Git

git命令与使用_learn_git_branching_notes

git命令与使用_learn_git_branching_notes

[转载] A successful Git branching model/GIT分支管理是一门艺术

A successful Git branching model

Git详解——Feature Branching:最流行的工作流