技术笔记(8)git的部分进阶功能

  • 学习笔记:

    • 与分支有关的git操作 branch、checkout、merge

      • 查看分支:

        • 查看当前分支信息:git branch
        • 查看远程分支信息:git branch -r
        • 查看所有分支信息,包括本地和远程:git branch -a
      • 分支与分支:

        • 切换到某分支:git checkout
        • 从当前节点新建一个分支:git checkout -b git
        • 删除掉一个分支:git branch -d
        • 将某个分支合并到当前分支:git merge
      • 回到过去或将来某个提交节点:

        • 回撤到某个提交点,文件也回到那个状态:

          git reset –hard

        • 回撤到某个提交点,文件保留被修改后的状态:

          git reset –soft

    • 处理merge conflict

      • 少量已修改的文件的处理方式:

        • 首先 cd <冲突文件所在目录>,例如:cd ~/Documents/Sample
        • vi <冲突文件名>,例如:vi a.txt
        • 输入i,进入insert模式,将想要的最终结果修改好
        • 按esc键退出insert模式,再按:键进入命令模式
        • 输入wq,退出该文件
        • 再次将冲突的文件add、commit之后,即顺利解决merge conflict
      • 大量且难修改可供参考的处理方式:

        • git checkout –ours <路径或文件名> 保留当前分支的内容
        • git checkout –theirs <路径或文件名> 保留对方分支的内容
    • 忽略无须版本管理的文件 .gitignore

      • 例如:在Unity游戏开发中,大部分时候只需要管理项目里的Asset、ProjectSetting、UserSetting文件。而可由Unity自动生成的且占容量极大的Library文件就没有版本管理的必要。

      • 在.gitignore文件中的输入格式:

        • 忽视某个特定文件:memo.txt
        • 忽视特定拓展名:*.avi
        • 作为例外情况,不忽视该文件:!study.avi
        • 忽略特定目录:study_asset/something_good/
        • 忽视根目录下的子目录:/sunofbeatch/
        • 注释行:用两个#扩起来
    • 撤销过去的提交,回滚提交 Revert

      • 实际上是在现在提交一个相反的,与过去的目标提交相抵消,并非直接让过去的提交消失
      • git revert
      • git revert HEAD~3 逆转当前分支当前节点往回数的第三次提交
      • git revert ^… 把这两次提交之间的所有提交以此逐个逆转
      • git revert -n ^… 用一次提交逆转这些提交
      • revert中发生冲突,与merge中冲突的处理方法一致
    • 提交历史合并为一条直线,变基 Rebase

      • rebase的逻辑是把所有历史提交都重新生成新的提交,所以提交id会改变

      • 但改变提交历史有一定的风险,最好不要把远程仓库已有的分支进行rebase,否则用普通的方法就无法成功推送了

      • 引用知乎用户“一个小号”的举例:

        • 原链接:https://www.zhihu.com/question/36509119/answer/1990894567

          一个好的 commits history,应该是这样的:

          *   e2e6451 (HEAD -> master) feture-c finished
          |\
          | * 516fc18 C.2
          | * 09112f5 C.1
          |/
          *   c6667ab feture-a finished
          |\
          | * e64c4b6 A.2
          | * 6058323 A.1
          |/
          *   2b24281 feture-b finished
          |\
          | * c354401 B.4
          | * 4bfefb8 B.3
          | * eb13f72 B.2
          | * c2c62b9 B.1
          |/
          * bbbba82 init
          

          而不是这样的:

          *   9f0c13b (HEAD -> master) feture-c finished
          |\
          | * 55be61c C.2
          | *   e18b5c5 merge master
          | |\
          | |/
          |/|
          * |   ee549c2 feture-a finished
          |\ \
          | * | 51f2126 A.3
          | * |   72118e2 merge master
          | |\ \
          | |/ /
          |/| |
          * | |   6cb16a0 feture-b finished
          |\ \ \
          | * | | 7b27b77 B.3
          | * | | 3aac8a2 B.2
          | * | | 2259a21 B.1
          |/ / /
          | * | 785fab7 A.2
          | * | 2b2b664 A.1
          |/ /
          | * bf9e77f C.1
          |/
          * 188abf9 init
          

          也不是这样的:

          * b8902ed (HEAD -> master) C.2
          * a4d4e33 C.1
          * 7e63b80 A.3
          * 760224c A.2
          * 84b2500 A.1
          * cb4c4cb B.3
          * 2ea8f0d B.2
          * df97f39 B.1
          * 838f514 init
          
      • 但说实话,什么时候用,怎么用,还是有一定疑惑

      • 另记录一个可供参考的git分支模型:

    • 合并多个提交,交互式变基 Squash

      • 把几个相连的提交合并成一个新的提交,冲突解决与merge类似
      • 同样的,由于涉及更改提交历史,慎重啊我的朋友
      • 还有不能对已经在远程仓库中存在的提交进行交互式变基
    • 拉取的具体实现 Pull

      • 实际上先从远程仓库的远程分支fetch到本地仓库里看不到的远程跟踪分支,再merge到我们能看到的本地分支。
      • 有个中介
      • 而只fetch的话,就是只获取远程分支的变化,先不急着改到本地分支
    • 暂存未提交的内容,贮藏 Stash

      • 当前功能做到一半,但还不适合提交。此时需要先去做另一部分的功能,或者merge另一个提交。此时就可以先把这部分没做完的贮藏起来,先搞定别的,再回来继续慢慢做。
    • 从其他分支上获取特定提交,遴选 cherry-pick

      • 即把另一个分支的某次提交,直接拿来吧你!
    • detached HEAD状态

      • 指不属于任何分支的无从属状态,一般发生于reset到过去的节点后,又做了一部分修改并提交,导致脱离所有的现有分支。
      • 在此状态下直接切换到某一分支的话,本次提交会直接丢失。
      • 解决:新建一个分支去接管