配置命令

git config

git config是 Git 自带的一个命令工具,用于帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置:

  1. /etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置。 如果在执行 git config 时带上 --system 选项,那么它就会读写该文件中的配置变量。 (由于它是系统配置文件,因此你需要管理员或超级用户权限来修改它。)
  2. ~/.gitconfig~/.config/git/config 文件:只针对当前用户。 你可以传递 --global 选项让 Git 读写此文件,这会对你系统上 所有 的仓库生效。
  3. 当前使用仓库的 Git 目录中的 config 文件(即 .git/config):针对该仓库。 你可以传递 --local 选项让 Git 强制读写此文件,虽然默认情况下用的就是它。。 (当然,你需要进入某个 Git 仓库中才能让该选项生效。)
1
2
3
4
5
6
7
8
9
10
11
# 查看所有的配置以及它们所在的文件
git config --list --show-origin

# 将user.name配置到~/.gitconfig下,值为wray
git config --global user.name wray

# 将user.name配置到当前路径下的项目config中,值为project-wray
git config user.name project-wray

# 检查配置项的值
git config user.name

git help

1
2
3
4
# 语法如下,<verb>表示命令动作,例如config、add、commit
git help <verb>
git <verb> --help
man git-<verb>
1
2
3
4
5
# 获取config命令的使用说明
git help config

# 获取config命令的简明说明
git config -h

.gitignore

git仓库的忽略文件,一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。

文件 .gitignore 的格式规范如下:

  • 所有空行或者以 # 开头的行都会被 Git 忽略。
  • 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
  • 匹配模式可以以(/)开头防止递归。
  • 匹配模式可以以(/)结尾指定目录。
  • 要忽略指定模式以外的文件或目录,可以在模式前加上叹号(!)取反。

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号(*)匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c); 问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。 使用两个星号(``)表示匹配任意中间目录,比如 a//z 可以匹配 a/za/b/za/b/c/z 等。

我们再看一个 .gitignore 文件的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 忽略所有的 .a 文件
*.a

# 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a

# 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO
/TODO

# 忽略任何目录下名为 build 的文件夹
build/

# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt

# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdf

在最简单的情况下,一个仓库可能只根目录下有一个 .gitignore 文件,它递归地应用到整个仓库中。 然而,子目录下也可以有额外的 .gitignore 文件。子目录中的 .gitignore 文件中的规则只作用于它所在的目录中。 (Linux 内核的源码库拥有 206 个 .gitignore 文件。)

多个 .gitignore 文件的具体细节超出了本书的范围,更多详情见 man gitignore

本地命令

本地命令表示在本地计算机可以执行的命令,不需要互联网。

git init

语法:git init

含义:将当前目录初始化为Git仓库,执行完后会在目录下生成一个.git隐藏目录。

如果在已有.git的目录下执行,会报错提示Git仓库已存在。

git clone

语法:git clone <url>

含义:克隆远程仓库到本地。

1
2
3
4
5
# 从github上克隆libgit2项目
git clone https://github.com/libgit2/libgit2

# 从github上克隆libgit2项目,并将项目的目录名更改为mylibgit
git clone https://github.com/libgit2/libgit2 mylibgit

git status

语法:git status

含义:检查当前文件状态

image-20231030161518755

图中的“nothing to commit, working tree clean”表示工作区很干净,所有已跟踪文件在上次提交后都未发生变更。

image-20231030161817320

图中的“Changes to be committed”表示已跟踪的文件,已经存放到Git暂存区中。

图中的“Untracked files”表示未跟踪的文件,不会被提交的git仓库。

git add

语法:git add <files>

含义:跟踪文件

1
2
# 跟踪README文件,README文件会处于暂存状态
git add README

git commit

语法:git commit

含义:这样会启动你选择的文本编辑器来输入提交说明,文件:w保存后,git会将暂存区的文件提交到git仓库。

1
2
3
4
5
6
7
8
# 指定-m,将提交说明与命令放在同一行,不用进入文本编辑器
git commit -m 'init project'

# 指定-a,将所有未暂存的文件一并提交,可以跳过git add添加暂存区的操作
git commit -a -m 'commit all un add file'

# 指定--amend,修改上一次的提交内容
git commit --amend -m '重新提交'

例如,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作:

1
2
3
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend

最终你只会有一个提交——第二次提交将代替第一次提交的结果。

当你在修补最后的提交时,与其说是修复旧提交,倒不如说是完全用一个 新的提交 替换旧的提交, 理解这一点非常重要。从效果上来说,就像是旧有的提交从未存在过一样,它并不会出现在仓库的历史中。

git rm

语法:git rm <file>

含义:将文件从已跟踪文件列表中移除

1
2
3
4
5
6
7
8
# 从已跟踪文件列表中移除PROJECT.md
git rm PROJECT.md

# 从已跟踪文件列表中移除PROJECT.md,连带删除工作目录中的PROJECT.md文件
git rm -f PROJECT.md

# 从已跟踪文件列表中移除PROJECT.md,保留工作目录的文件
git rm --cached PROJECT.md

git rm支持glob模式,git rm 命令后面可以列出文件或者目录的名字。比如:

1
$ git rm log/\*.log

注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开。 此命令删除 log/ 目录下扩展名为 .log 的所有文件。 类似的比如:

1
$ git rm \*~

该命令会删除所有名字以 ~ 结尾的文件。

git mv

语法:git mv <old_file> <new_file>

含义:修改已跟踪文件的文件名。

1
2
# 将README文件改为README.md
git mv README README.md

其实,运行 git mv 就相当于运行了下面三条命令:

1
2
3
$ mv README.md README
$ git rm README.md
$ git add README

git log

语法:git log

含义:不传入任何参数的默认情况下,git log 会按时间先后顺序列出所有的提交,最近的更新排在最上面。 正如你所看到的,这个命令会列出每个提交的 SHA-1 校验和、作者的名字和电子邮件地址、提交时间以及提交说明。

其中一个比较有用的选项是 -p--patch ,它会显示每次提交所引入的差异(按 补丁 的格式输出)。 你也可以限制显示的日志条目数量,例如使用 -2 选项来只显示最近的两次提交。

git reset HEAD

语法:git reset HEAD <file>

含义:取消暂存的文件

git restore

语法:git restore <file>

含义:撤销对文件的修改。

git checkout — <file>与git restore都可以做到同样的功能,不过现在已不建议使用。

git remote

语法:git remote

含义:查看已经配置的远程仓库服务器。

远程仓库可以在你的本地主机上

你完全可以在一个“远程”仓库上工作,而实际上它在你本地的主机上。 词语“远程”未必表示仓库在网络或互联网上的其它位置,而只是表示它在别处。 在这样的远程仓库上工作,仍然需要和其它远程仓库上一样的标准推送、拉取和抓取操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 查看远程仓库服务器的简写,一般默认为origin
git remote

# 查询远程仓库使用 Git 保存的简写与其对应的 URL
git remote -v

# 为当前git仓库添加一个远程仓库
git remote add pb https://github.com/paulboone/ticgit

# 远程仓库重命名,将pb改为paul
git remote rename pb paul

# 删除远程仓库
git remote remove paul

# 设置指定远程仓库的仓库地址
git remote set-url origin <新的仓库地址>

git tag

语法:git tag

含义:在 Git 中列出已有的标签

Git标签分为轻量标签(lightweight)与附注标签(annotated)。一般使用附注标签。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 指定-a,创建附注标签。-a后面是标签号,-m是标签的说明
git tag -a v1.4 -m "my version 1.4"

# 在git tag后不加任何参数,指定输入标签名,表示创建轻量标签
git tag v1.4-lw

# 指定版本打标签。9fceb02是提交历史的校验和的部分(前部分)
git tag -a v1.2 9fceb02

# 查询标签信息
git show v1.2

# 推送标签到远程origin仓库
git push origin v1.2

# 删除标签
git tag -d v1.2

# 删除远程仓库中的标签
git push origin --delete <tagname>

git branch

查看本地分支列表:git branch

查看远程分支列表:git remote show <remote>

<remote> 是指远程仓库名字,一般是origin。

image-20231206170139401

创建分支:git branch <branchname>

切换分支:git checkout <branchname>

切换并创建分支:git checkout -b <branchname>

切换并创建分支,并且跟踪指定远程分支:git checkout -b <branch> <remote>/<branch>

git checkout --track origin/serverfixgit checkout serverfix是git的快捷方式,它们在切换分支是会自动创建本地分支,名称同远程分支名一样,并且自动跟踪该远程分支。

注意,对于新创建的远程分支,本地需要先git fetch拉取最新信息后,再checkout。

手动跟踪远程分支:git branch -u <origin>/<branchname>

删除分支:git branch -d <branchname>

查看本地分支信息:git branch -v

查看本地分支信息对应的远程分支信息:git branch -vv

合并分支:git merge <branchname>

合并时遇到冲突的场景:

image-20231030173522040

此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。 你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件:

image-20231030173602974

最后对冲突文件执行git add <file>,一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。

冲突都合并并且暂存完之后,执行git commit,完成此次的冲突合并操作。

git branch --merged:查看已合并到当前分支的其他分支,表示这些分支已经合并了,可以删除。

git branch --no-merged:查看未合并到当前分支的其他分支,此时执行删除分支操作会失败,除非改为使用git branch -D <branchname>命令强制删除。

网络命令

网络命令就是指需要互联网才能获取到信息的命令。

git fetch

语法:git fetch <remote>

含义:这个命令会访问远程仓库,从中拉取所有你还没有的数据。 执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。

git push

语法:git push <remote> <branch>

含义:将本地Git仓库推送到远程仓库

1
2
# 将远程仓库origin中的serverfix分支删除
git push origin --delete serverfix