Git 从入门到不放弃

Guangwang Huang

Created: 2021-10-07 Thu 15:57

1 前言

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

2 Git 优点

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

3 基本概念

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

3.1 提交 (commit)

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

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

3.1.1 commit

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

2021-10-07-git-commit.png

3.1.2 commit id

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

其他简便的表示方法:

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

更多请参考 man gitrevisions

3.2 HEAD

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

3.3 仓库 (repository)

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

  • 本地仓库 (local) 即 .git/ 目录,除非你很确定你在做什么,否则别修改其中的文件。
  • 远端仓库 (remote) ,即在服务器的仓库
    • 一个本地仓库可对应多个远端
    • 本地通过 push/fetch/pull 子命令与远端交互

3.4 分支 (branch)

  • 可以离线创建和管理,无需服务器交互
  • remote-tracking branch ,名字格式是 <remote>/<branch>

    此种分支你无法提交更改

  • tracking branch: 用于追踪远端分支的分支

    通过 fetch/pull/push 子命令来与远端进行同步

    参考 Git: What is a tracking branch? - Stack Overflow

3.5 存储区域

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

  1. working tree
  2. staging area

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

详细内容,请参考 git-add

3.5.1 working tree

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

3.5.2 staging area (index)

通常翻译为“暂存区”。

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

3.6 文件状态

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

    可以细分为三种文件:

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

3.6.1 文件状态转换图

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

3.7 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 概念

3.8 ignore 文件

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

3.8.1 不同作用范围的 ignore 文件

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

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

4 基本操作

4.1 分支相关

  • git checkout foo 切换到某个分支
  • git checkout -b barHEAD 创建新分支,并切换到它
  • git status 查看当前工作区的状态
  • git add foo.clj 把文件当前内容放入 staging area

4.1 分支相关

  • git commit -m "hello world" 提交
  • git commit --amend 更改 HEAD commit
  • git diff 查看变更

    默认对比 working area vs. index 的差异;

    --cached 对比 index 与上一次 commit 的差异。

4.2 提交日志查看

  • git log 查看当前分支的提交日志(历史)
  • git log --oneline --decorate --graph --all 显示所有分支的提交历史

    /img/slides/2021-10-07-git-log-all.png

4.3 分支合并操作

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

4.3.1 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

4.3.2 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

4.4 与远端相关的操作

  • git clone https://github.com/whatacold/texttoolkit.git 从远端克隆到本地
  • git remote add origin https://github.com/whatacold/texttoolkit.git 添加一个远端到本地仓库
  • git remote 查看远端,加 -v 同时查看地址

4.4 与远端相关的操作

  • git push origin 把当前分支同步到远端
  • git fetch origin 从远端同步最新版本,但不改变 tracking branch
  • git pull origin 拉取最新代码并合并,相当于这两步: git fetch + git merge

5 协作模式

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

5.1 Centralized Workflow

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

2021-10-07-git-centralized.png

5.2 Integration-Manager Workflow

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

2021-10-07-git-integration-manager.png

6 Tips

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

7 参考资料