Git 从入门到不放弃


前言

  • 起因:Git 的上手有点难度
  • 目的:介绍 Git 基本概念和操作,帮你更快上手 Git

Git 优点

  • 本地即可实现文件的版本管理,无需服务器
  • 极轻量的分支操作,方便多分支并行开发
  • 强大的功能: rebase, stash, bisect 等等

基本概念

注:为避免不正确翻译反而给你带来困惑,除非毫无争议的概念,此处尽量采用英文。

提交 (commit)

一个提交是一次变更记录,由 commit 子命令生成。

多次提交环环相扣,形成树状提交历史: /img/slides/2021-10-07-git-log-tree.png

commit

一个 commit 包含:commit id 、作者名字和邮箱、时间戳和 commit message (描述信息)

/img/slides/2021-10-07-git-commit.png

commit id

定义:一串40 个 [a-f] 字符( SHA1 摘要值)

其他简便的表示方法:

  1. 若不冲突,也可以开头的几个字符表示
  2. 分支名称
  3. HEAD 当前分支的最后一次提交
  4. 特殊语法, master^ 表示 master 的前一次 revision

更多请参考 man gitrevisions

HEAD

一种游标或者指针,同一时刻只能指向某个 commit ,此即 HEAD

仓库 (repository)

仓库用于存放所有版本管理相关的数据,包括提交、分支等。

  • 本地仓库 (local) 即 .git/ 目录,除非你很确定你在做什么,否则别修改其中的文件。
  • 远端仓库 (remote) ,即在服务器的仓库

    • 一个本地仓库可对应多个远端
    • 本地通过 push/fetch/pull 子命令与远端交互

分支 (branch)

  • 可以离线创建和管理,无需服务器交互
  • remote-tracking branch ,名字格式是 <remote>/<branch> 此种分支你无法提交更改
  • tracking branch: 用于追踪远端分支的分支 通过 fetch/pull/push 子命令来与远端进行同步 参考 Git: What is a tracking branch? - Stack Overflow

存储区域

文件除了已经存入仓库之外,还有两个地方:

  1. working tree
  2. staging area

Git 比 SVN 多了 staging area 这一个概念,请务必要理解它。

详细内容,请参考 git-add

working tree

  • 可以理解为在文件系统中看到的目录和文件的状态、内容;
  • 一个仓库默认有一个 working tree ,但也可以有多个

staging area (index)

通常翻译为“暂存区”。

index 是 working tree 的一个快照( snapshot ),下次提交的就是这个快照。

文件状态

  • untracked 未纳入 git 中管理的文件
  • tracked 已纳入 git 中管理的文件

    可以细分为三种文件:

    • unmodified 未变动的文件
    • modified 已经更改,但是未放入 staging area 的内容
    • staged 已经更改,且已放入 staging area 的内容

文件状态转换图

文件状态转换图: /img/slides/2021-10-07-git-file-states.png

hunk: 差异块

  • hunk 概念:由 @@@...@@@ 包围的一块连续的差异

    index fabadb8,cc95eb0..4866510
    --- a/describe.c
    +++ b/describe.c
    @@@ -98,20 -98,12 +98,20 @@@
    - static void describe(char *arg)
    ++static void describe(char *arg, int last_one)
      {
     +      unsigned char sha1[20];
     +      struct commit *cmit;
            struct commit_list *list;
    
  • hunk 比文件粒度更细,用于操作文件的一部分 “古老”的 diff/patch 工具就已有 hunk 概念

ignore 文件

  • 用于忽略编译结果文件等文件
  • 文件格式:文本文件,一行表示一个忽略规则
  • 支持通配符,比如所有 .o 结尾的文件: *.o
  • 可忽略目录,比如 obj/

不同作用范围的 ignore 文件

  • $HOME/.config/git/ignore 当前用户默认,对用户的所有工程都起作用
  • $GIT_DIR/.gitignore 工程内,此文件自身也纳入 Git 管理
  • $GIT_DIR/info/exclude 工程内,同时不纳入 Git 管理(不推荐)

注:工程内的 ignore 文件优先级高于 home 目录的。

基本操作

分支相关

  • git checkout foo 切换到某个分支
  • git checkout -b barHEAD 创建新分支,并切换到它
  • git status 查看当前工作区的状态
  • git add foo.clj 把文件当前内容放入 staging area
  • git commit -m "hello world" 提交
  • git commit --amend 更改 HEAD commit
  • git diff 查看变更 默认对比 working area vs. index 的差异; 加 --cached 对比 index 与上一次 commit 的差异。

提交日志查看

  • git log 查看当前分支的提交日志(历史)
  • git log --oneline --decorate --graph --all 显示所有分支的提交历史 /img/slides/2021-10-07-git-log-all.png

分支合并操作

命令: git merge ,按是否 fast-forward 可以分为两种情况。

fast-forward merge

执行 git merge --ff-only topic

不带任何选项时, Git 会优先使用 ff 方式,建议明确加选项。

    Before             vs.       After
                                                 topic
          A---B---C topic                        | master
         /                                       |/
    D---E master                 D---E---A---B---C

non-fast-forward merge

执行 git merge --no-ff topic ,会有一个真正的 merge commit 。

示例1:

    Before             vs.       After

          A---B---C topic              A---B----C topic
         /                            /          \
    D---E master                 D---E------------F master

示例2:

    Before              vs.          After
          A---B---C topic                  A-----B-----C topic
         /                                /             \
    D---E---F---G---H master         D---E---F---G---H---I master

与远端相关的操作

  • git clone https://github.com/whatacold/texttoolkit.git 从远端克隆到本地
  • git remote add origin https://github.com/whatacold/texttoolkit.git 添加一个远端到本地仓库
  • git remote 查看远端,加 -v 同时查看地址
  • git push origin 把当前分支同步到远端
  • git fetch origin 从远端同步最新版本,但不改变 tracking branch
  • git pull origin 拉取最新代码并合并,相当于这两步: git fetch + git merge

协作模式

详细请参考: Git - Distributed Workflows - git-scm.com

Centralized Workflow

一般企业内部的项目采用的是此种模式

/img/slides/2021-10-07-git-centralized.png

Integration-Manager Workflow

GitHub/GitLab 的协作,采用的就是这种模式

/img/slides/2021-10-07-git-integration-manager.png

COMMENT 黑科技

git rebase 更改分支的代码基( revision 会变 )

git cherry-pick: 摘取其他分支的一个、或者多个 commit

git blame: bug 该“责怪”谁

某行新加的代码由谁引入的

某行代码被谁删除引发 bug 的

git bisect: 二分查找法定位问题在何时引入

Tips

  • 常用 git status 查看工作区状态,比如 commit 之前确认改动是否符合预期
  • 提交到远端的 commit ,再更改可能对别人造成影响,因此不要着急 push
  • 多人协作的分支,已经 pushed 的 commit ,不要再 rebase 更改

参考资料


comments powered by Disqus