Shell Shell
Home
Shell
Linux
Network
Git
Blog (opens new window)
GitHub (opens new window)
Home
Shell
Linux
Network
Git
Blog (opens new window)
GitHub (opens new window)
  • 玩转 Git 三剑客

    • 目录
    • Git 基础
      • 安装 Git
        • 使用安装包安装
        • 使用 Scoop 安装
        • 使用 winget 安装
      • 使用 Git 之前需要做的最小配置
      • 创建第一个仓库并配置 local 用户信息
      • 通过几次 commit 来认识工作区和暂存区
      • 给文件重命名的简便方法
      • 通过 git log 查看版本演变历史
      • gitk:通过图形界面工具来查看版本历史
      • 探密.git 目录
      • commit、tree 和 blob 三个对象之间的关系
      • 小练习:数一数 tree 的个数
      • 分离头指针情况下的注意事项
      • 进一步理解 HEAD 和 branch
  • git
  • 玩转 Git 三剑客
JaimeZeng
2022-03-16
目录

Git 基础

文档

  • Git 官网:Git (git-scm.com) (opens new window)
  • Git 文档:Git - Book (git-scm.com) (opens new window)

# 安装 Git

文档:Git - 安装 Git (git-scm.com) (opens new window)

  • linux 下直接使用包管理器(dnf/apt/pacman)安装
  • windows 下使用二进制安装包安装或者使用 scoop/winget 安装

# 使用安装包安装

(Windows)打开 Git - Downloading Package (git-scm.com) (opens new window) 浏览器会自动下载 git 安装包。下载完成后双击安装包点击安装(安装过程中一直点击下一步即可)。

# 使用 Scoop 安装

# 打开 PowerShell 远程权限

Set-ExecutionPolicy RemoteSigned -scope CurrentUser
1

# 自定义 Scoop 和 App 安装目录

Scoop 默认将 Scoop 和 App 安装在 $HOME/scoop 目录下。

$env:SCOOP='D:\Applications\Scoop'
[Environment]::SetEnvironmentVariable('SCOOP', $env:SCOOP, 'User')
1
2

# 安装 Scoop

Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')

# or shorter
iwr -useb get.scoop.sh | iex
1
2
3
4

# 安装 git

scoop install git
1

# 使用 winget 安装

  1. 打开 Releases · microsoft/winget-cli (github.com) (opens new window) 下载 winget 安装包安装 winget。
  2. 使用 winget install --id Git.Git 安装 git。

# 使用 Git 之前需要做的最小配置

  1. 设置你的用户名和邮件地址

    $ git config --global user.name "Jaime"
    $ git config --global user.email Jaime@zxj.guru
    
    1
    2
  2. 配置作用域:

    • --local:只对当前目录下的仓库有效
    • --global:对当前用户下所有仓库有效
    • --system:对系统所有登录用户有效
  3. 查看配置:git config —list [--local | --global | --system]

$ git config -l --global # 查看用户配置
includeif.gitdir:E:/Github/JaimeZeng/.path=~/.gitconfig-JaimeZeng
includeif.gitdir:E:/Github/Ryanjiena/.path=~/.gitconfig-Ryanjiena
credential.helper=manager-core
$ git config -l --local # 查看本地配置
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
remote.origin.url=git@gitcode.net:qq_365/note-assets.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.main.remote=origin
branch.main.merge=refs/heads/master
user.email=43134606+Ryanjiena@users.noreply.github.com
user.name=Ryanjiena
$ git config -l --system # 查看系统配置
core.symlinks=false
core.autocrlf=true
core.fscache=true
color.diff=auto
color.status=auto
color.branch=auto
color.interactive=true
help.format=html
diff.astextplain.textconv=astextplain
rebase.autosquash=true
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
credential.helper=helper-selector
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 创建第一个仓库并配置 local 用户信息

  1. 创建 Git 仓库

    • 把已有的项目代码纳入 git 管理:很早之前本地生成了一个 git 的仓库,开发了一段时间,想把这个 git 仓库提交到公司 git 服务器新建的 project 中。

      $ cd project-directory # 进入到项目文件夹内
      $ git remote add origin git@your_git_server:your_group/your_project.git # 关联远程仓库
      $ git push -u origin --all # 推送所有分支
      $ git push -u origin --tags # 推送所有标签
      
      1
      2
      3
      4
    • 新建的项目直接使用 git 管理:本地有个项目代码写了一段时间了,但还没有用 git 管理起来,现在想用 git 在本地帮着记录变更的版本。

      $ cd project-directory # 进入到项目文件夹内
      $ git init # 初始化,会创建出 .git 目录
      $ git add . # 把项目文件加入到 git 的暂存区
      $ git commit -m "Initial commit" # 把项目文件加入到 git 的暂存区
      
      1
      2
      3
      4
  2. 配置 local 用户信息

    $ git config --local user.email "Raynjiena@gmail.com"
    $ git config --local user.name "zxja"
    
    1
    2
  3. 本地仓库配置中:local > global

➜ ~/VSCodeProject git init learning-git
Initialized empty Git repository in /home/jaime/VSCodeProject/learning-git/.git/
➜ ~/VSCodeProject cd learning-git
➜ learning-git main ✗ ls -la
drwxr-xr-x@ - jaime 15 Mar 13:19 .git
➜ learning-git main ✗ echo "## hello world" > README.md
➜ learning-git main ✗ git config --local user.email "Raynjiena@gmail.com"
➜ learning-git main ✗ git config --local user.name "zxja"
➜ learning-git main ✗ git config --list --global
user.email=43134606+Ryanjiena@users.noreply.github.com
user.name=Ryanjiena
init.defaultbranch=main
➜ learning-git main ✗ git config --list --local
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
user.email=Raynjiena@gmail.com
user.name=zxja
➜ learning-git main ✗ git add README.md
➜ learning-git main ✗ git commit -m "add README.md"
[main (root-commit) 89dc6ad] add README.md
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
➜ learning-git main ✓ git log --pretty="%h - %s(%ae)"
89dc6ad - add README.md(Raynjiena@gmail.com) # 这里邮箱为 local 里配置而非用户 global 里的配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 通过几次 commit 来认识工作区和暂存区

  • add 将工作区添加进暂存区,跟踪新文件
    • git add -u:将文件的修改、文件的删除,添加到暂存区。
    • git add . | -A | --all:将文件的修改,文件的删除,文件的新建,添加到暂存区。
  • commit 提交更新
    • git commit -m 'commit-message':提交暂存区的改动
    • git commit -am 'commit-message':直接提交工作区内的改动
  • status 查看哪些文件处于什么状态
➜ learning-git main ✓ nvim working-add-staging.md
➜ learning-git main ✓ bat working-add-staging.md
zsh: command not found: bat
➜ learning-git main ✓ cat working-add-staging.md
## 通过几次 commit 来认识工作区和暂存区

- add 将工作区添加进暂存区
  - `git add -u`:将文件的修改、文件的删除,添加到暂存区。
  - `git add . | -A | --all`:将文件的修改,文件的删除,文件的新建,添加到暂存区。
- commit 提交

➜ learning-git main ✓ git add -u
➜ learning-git main ✓ git status
On branch main
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        05.working-add-staging.md

nothing added to commit but untracked files present (use "git add" to track)
➜ learning-git main ✓ git commit -m "add 05.working-add-staging"
On branch main
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        working-add-staging.md

nothing added to commit but untracked files present (use "git add" to track)
➜ learning-git main ✓ git add --all
➜ learning-git main ✗ git commit -m "add 05.working-add-staging"
[main 3a387fc] add 05.working-add-staging
 1 file changed, 7 insertions(+)
 create mode 100644 working-add-staging.md
➜ learning-git main ✓ git log --pretty="%h - %s(%ae)"
3a387fc - add 05.working-add-staging(Raynjiena@gmail.com)
89dc6ad - add README.md(Raynjiena@gmail.com)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 给文件重命名的简便方法

  1. 文件重命名

    $ mv readme readme.md # 删除文件 readme 创建新文件 readme.md
    $ git add readme.md # 添加到暂存区
    $ git rm readme # 将原来的文件删除掉
    
    # 或者直接合并为一步
    $ git mv readme readme.md # 将 readme 重新命名成 readme.md
    
    1
    2
    3
    4
    5
    6
  2. git reset 清除暂存区内容 ``git reset --hard清除暂存区和工作区内容

  3. git config core.ignorecase 设置是否忽略大小写

# 重命名文件后,添加工作区的文件到暂存区,然后将原暂存区文件删除
➜ learning-git main ✓ mv README.md readme.md
➜ learning-git main ✗ git add readme.md
➜ learning-git main ✗ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   readme.md

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    README.md

➜ learning-git main ✗ git rm README.md
rm 'README.md'
➜ learning-git main ✗ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        renamed:    README.md -> readme.md

# 使用 git reset --hard 命令直接删除工作区和暂存区内所有修改,恢复至上一次提交时的状态
➜ learning-git main ✗ git reset --hard
HEAD is now at f1ac2bb add 05.working-add-staging
➜ learning-git main ✓ git status
On branch main
nothing to commit, working tree clean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 直接重命名暂存区里的文件
➜ learning-git main ✓ git mv README.md readme.md
➜ learning-git main ✗ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        renamed:    README.md -> readme.md
➜ learning-git main ✗ git add .
# 使用 git reset 命令删除暂存区里的改动,工作区的改动还在
➜ learning-git main ✗ git reset
Unstaged changes after reset:
D       README.md
➜ learning-git main ✗ git status
On branch main
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    README.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        readme.md

no changes added to commit (use "git add" and/or "git commit -a")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 通过 git log 查看版本演变历史

  • 常用命令

    • git log --all 查看所有分支的历史
    • git log --all --graph 查看图形化的 log 地址
    • git log --oneline 查看单行的简洁历史
    • git log --oneline -n4 查看最近的四条简洁历史
    • git log --oneline --all -n4 --graph 查看所有分支最近 4 条单行的图形化历史
    • git help --web log 使用浏览器查看 git log 的帮助文档
  • git log 选项说明

    • -p 按补丁格式显示每个更新之间的差异。

    • --stat 显示每次更新的文件修改统计信息。

    • --shortstat 只显示 --stat 中最后的行数修改添加移除统计。

    • --name-only 仅在提交信息后显示已修改的文件清单。

    • --name-status 显示新增、修改、删除的文件清单。

    • --abbrev-commit 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。

    • --relative-date 使用较短的相对时间显示(比如,“2 weeks ago”)。

    • --graph 显示 ASCII 图形表示的分支合并历史。

    • --pretty 使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)。

      • %H 提交对象(commit)的完整哈希字串
      • %h 提交对象的简短哈希字串
      • %T 树对象(tree)的完整哈希字串
      • %t 树对象的简短哈希字串
      • %P 父对象(parent)的完整哈希字串
      • %p 父对象的简短哈希字串
      • %an 作者(author)的名字
      • %ae 作者的电子邮件地址
      • %ad 作者修订日期(可以用 -date= 选项定制格式)
      • %ar 作者修订日期,按多久以前的方式显示
      • %cn 提交者(committer)的名字
      • %ce 提交者的电子邮件地址
      • %cd 提交日期
      • %cr 提交日期,按多久以前的方式显示
      • %s 提交说明
  • git 配置图形化查看日志:git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --all"

  • 创建并切换到新分支:git checkout -b branch-name

➜ learning-git main ✓ git log --oneline # 查看单行的简洁历史
f1ac2bb (HEAD -> main) add 05.working-add-staging
f1de4a6 add README.md
➜ learning-git main ✓ git checkout -b develop f1de4a6 # 创建并切换到 develop 分支
Switched to a new branch 'develop'
➜ learning-git develop ✓ nvim 07.git-log.md
➜ learning-git develop ✓ git add .
➜ learning-git develop ✗ git commit -m "add 07.git-log.md"
[develop 2db0f11] add 07.git-log.md
 1 file changed, 2 insertions(+)
 create mode 100644 07.git-log.md
➜ learning-git develop ✓ git status
On branch develop
nothing to commit, working tree clean
# 单行、图形化查看历史
➜ learning-git develop ✓ git log --oneline --graph --color --all
* 2db0f11 (HEAD -> develop) add 07.git-log.md
| * f1ac2bb (main) add 05.working-add-staging
|/
* f1de4a6 add README.md
# 配置 git alias
➜ learning-git develop ✓ git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --all"
# 使用 alias 查看历史记录
➜ learning-git develop ✓ git lg
* 2db0f11 - (HEAD -> develop) add 07.git-log.md (2 minutes ago) <zxja>
| * f1ac2bb - (main) add 05.working-add-staging (72 minutes ago) <zxja>
|/
* f1de4a6 - add README.md (74 minutes ago) <zxja>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# gitk:通过图形界面工具来查看版本历史

gitk 详细操作可看 gitk 详解_ElectronR 的博客-CSDN 博客_gitk (opens new window)。不推荐使用这个工具,建议使用 SmartGit、GitKarken、Sourcetree、TortoiseGit、VSCode 里的 GitLens 插件等。

➜ learning-git develop ✓ sudo apt install gitk -y
➜ learning-git develop ✓ gitk
1
2

# 探密.git 目录

➜ learning-git develop ✓ ls -la ./.git
.rw-r--r--  18 jaime 16 Mar 17:20 COMMIT_EDITMSG
.rw-r--r-- 141 jaime 16 Mar 16:08 config
.rw-r--r--  73 jaime 16 Mar 16:07 description
.rw-r--r-- 252 jaime 16 Mar 17:34 gitk.cache
.rw-r--r--  24 jaime 16 Mar 17:19 HEAD
drwxr-xr-x   - jaime 16 Mar 16:07 hooks
.rw-r--r-- 217 jaime 16 Mar 17:20 index
drwxr-xr-x   - jaime 16 Mar 16:07 info
drwxr-xr-x   - jaime 16 Mar 16:08 logs
drwxr-xr-x   - jaime 16 Mar 17:20 objects
.rw-r--r--  41 jaime 16 Mar 16:12 ORIG_HEAD
drwxr-xr-x   - jaime 16 Mar 16:07 refs
1
2
3
4
5
6
7
8
9
10
11
12
13
  • .git 目录

    • COMMIT_EDITMSG:最新提交的一次 Commit Message,git 系统不会用到,给用户一个参考

    • config:当前 git 仓库的配置文件

    • description:仓库的描述信息,主要给 gitweb 等 git 托管系统使用

    • HEAD (映射到 ref 引用,指向当前所在的分支),例如当前在 develop 分支,实际指向地址是 refs/heads/develop

    • hooks(钩):存放一些 shell 脚本

    • index:暂存区(stage),一个二进制文件

    • info/exclude:存放仓库的一些信息

    • logs:保存所有更新的引用记录

    • objects:存放所有的 git 对象。以 hash 的二进制方式来存储,这个组件的名称就是文件夹名称 + 文件夹中的文件的名称

    • ORIG_HEAD:HEAD 指针的前一个状态

    • FETCH_HEAD:是一个版本链接,指向着目前已经从远程仓库取下来的分支的末端版本

    • refs/heads|tags:保存当前最新的一次提交|标签的哈希值

    ➜ learning-git develop ✓ cat ./.git/HEAD # 当前 HEAD 指向 develop 分支
    ref: refs/heads/develop
    ➜ learning-git develop ✓ cat ./.git/config # 当前仓库 git 配置
    [core]
            repositoryformatversion = 0
            filemode = true
            bare = false
            logallrefupdates = true
    [user]
            email = Raynjiena@gmail.com
            name = zxja
    ➜ learning-git develop ✓ ls -la ./.git/refs/heads # 当前项目所有分支
    .rw-r--r-- 41 jaime 16 Mar 17:20 develop
    .rw-r--r-- 41 jaime 16 Mar 16:10 main
    ➜ learning-git develop ✓ cd ./.git/objects/2d
    ➜ learning-git/.git/objects/2d develop ✗ ls
    b0f11ad7a08f9d61100c553a235e61ebcce1f1
    # 查看 2db0f11ad7a08f9d61100c553a235e61ebcce1f1 commit 对象的内容
    ➜ learning-git/.git/objects/2d develop ✗ git cat-file -p 2db0f11ad7a08f9d61100c553a235e61ebcce1f1
    tree a758fb2bd07c7f8316acf378907fda8c5c3e0875
    parent f1de4a64d721d5b4193774d44fb5a7005010919b
    author zxja <Raynjiena@gmail.com> 1647422441 +0800
    committer zxja <Raynjiena@gmail.com> 1647422441 +0800
    
    add 07.git-log.md
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
  • git 常用组件 (opens new window)

    • Tag
    • Commit:一个 commit 对象里面会包含有 tree(相当于文件夹)、parent、author 和 committer
    • Tree:一个 tree 里面会包含 tree 和 blob(具体的内容)
    • BLOB:一个 blob 指的就是具体的文件内容,blob 与文件名无关,只与文件内容有关,即文件内容相同,在 git 中是同一个 blob。
    ➜ learning-git develop ✓ git lg
    * 2db0f11 - (HEAD -> develop) add 07.git-log.md (29 hours ago) <zxja>
    | * f1ac2bb - (main) add 05.working-add-staging (30 hours ago) <zxja>
    |/
    * f1de4a6 - add README.md (30 hours ago) <zxja>
    ➜ learning-git develop ✓ git cat-file -t 2db0f11 # 2db0f11 为 提交
    commit
    ➜ learning-git develop ✓ git cat-file -p 2db0f11 # 2db0f11 commit对象提交的内容包含tree、parent、author 和 committer
    tree a758fb2bd07c7f8316acf378907fda8c5c3e0875
    parent f1de4a64d721d5b4193774d44fb5a7005010919b
    author zxja <Raynjiena@gmail.com> 1647422441 +0800
    committer zxja <Raynjiena@gmail.com> 1647422441 +0800
    
    add 07.git-log.md
    ➜ learning-git develop ✓ git cat-file -p a758fb # a758fb tree 对象包含 blob
    100644 blob 8f756dc31f5c79d9c4782514e1dde7c1ac575669    07.git-log.md
    100644 blob 4ebdc4ec7cc0987890d14f0338b1278fda531d26    README.md
    ➜ learning-git develop ✓ git cat-file -p 8f756dc # 8f756dc tree 对象内容
    ## 通过 git log 查看版本演变历史
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
  • git cat-file 从 git 取回数据

    • git cat-file -p 自动判断对象类型,并显示其内容
    • git cat-file -t 显示对象类型
    • git cat-file -s 显示对象大小

# commit、tree 和 blob 三个对象之间的关系

# 小练习:数一数 tree 的个数

# 分离头指针情况下的注意事项

# 进一步理解 HEAD 和 branch

目录

← 目录

Theme by Vdoing | Copyright © 2020-2022 JaimeZeng | ❤️ | CC BY-NC-SA 4.0
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式