1. 集中式 vs. 分布式
1.1 集中式版本控制系统(SVN和CVS)
先从中央服务器取得最新的代码版本,然后在本地编写代码,编写完成后将本地代码推送至中央服务器。
缺点:必须联网。
1.2 分布式版本控制系统(Git)
分布式版本控制系统没有“中央服务器”的概念,每个人的电脑上都是一个完整的版本库。
优点:安全性要高,不需要联网。
2. 设置用户名和邮箱地址
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
git config命令的--global参数,使用这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和邮箱地址。
3. 版本回退
- 查看历史记录:
git log - 回退到上一个版本:
git reset --hard HEAD^ 
用HEAD表示当前版本,上一个版本就是
HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100(大小写敏感)
注意:当返回上一个版本后,当前版本将消失,想再次查看当前版本,则需要知道当前版本的commit id
$ git reset --hard [commit_id]
总结:
- HEAD指向的版本就是当前版本,Git 允许用户在版本的历史之间穿梭
 - 穿梭前,用
git log可以查看提交历史,以便确定要回退到哪个版本 - 要重返未来,用
git reflog查看命令历史,以便确定要回到未来的哪个版本 
4. 工作区与暂存区
4.1 工作区(Working Directory)
就是用户在电脑里能看到的目录,比如一个testgit文件夹就是一个工作区。(有正在编辑但未持久化之意)
4.2 暂存区
Git 的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有 Git 为我们自动创建的第一个分支main,以及指向main的一个指针叫HEAD。
当用户把文件向 Git 版本库中添加的时候,是分两步执行的:
- 第一步:用
git add把文件添加进去,实际上就是把文件修改添加到暂存区stage - 第二步:用
git commit提交更改,实际上就是把暂存区的所有内容提交到当前master分支。 
需要澄清的一点是:
在 Git 中,git commit始终提交的是暂存区(Staging Area)的内容,而非当前工作区(Working Directory)的最新修改:
- 修改文件 A(生成版本 v1)
 - 执行
git add A(将 v1 添加至暂存区) - 再次修改文件 A(生成版本 v2)
 - 执行
git commit(提交的是暂存区的 v1 版本) 
# 清空暂存区:
$ git reset
# 清空暂存区并还原修改(⚠️ 有数据丢失风险)至上一次commit记录:
$ git reset --hard
# 等价于
$ git reset --hard HEAD
5. 修改撤销
# 把[filename]文件在工作区的修改全部撤销,回到上一次commit记录
$ git checkout -- [filename]
# 把暂存区(add后)的修改撤销掉(unstage),重新放回工作区
$ git reset HEAD [file_name]
# 注意和下面区分(清空暂存区并还原修改至上一次commit记录)
$ git reset --hard HEAD
6. 分支管理
6.1 创建与合并分支
# 查看分支,查询结果前带'*'的,表示处于当前分支
$ git branch
# 显示本地分支与上游分支的跟踪关系
$ git branch -vv
# 创建分支,分支名为[branchname]
$ git branch [branchname]
# 切换分支[branchname]
$ git checkout [branchname]
# 创建并切换到分支[branchname]
$ git checkout -b [branchname]
# 合并分支名为[branchname]的分支到当前分支
$ git merge [branchname]
# 删除分支名为[branchname]的分支
$ git branch -d [branchname]
# 丢弃一个没有被合并过的分支(强行删除)
$ git branch -D
6.2 新建分支修复 Bug
修复bug时,通常会通过创建新的bug分支进行修复,然后合并,最后删除。当手头工作没有完成时,先把工作现场git stash一下,可以把当前工作现场“储藏”起来,然后去修复bug,修复后,再git stash pop或者git stash apply,回到工作现场。
# 恢复后,stash内容并不删除,需要用git stash drop来删除
$ git stash apply
# 恢复的同时把stash内容也删除
$ git stash pop
# 查看储藏的工作现场
$ git stash list
# 多次stash后,恢复指定的stash -> 通过上面指令查询后使用
$ git stash apply stash@{0}
7. 多人协作
# 查看远程库的信息、名称
$ git remote
# 显示更详细的信息;可以抓取和推送的远程仓库的地址
$ git remote -v
# 将本地的main分支提交推送到远程库的main分支
$ git push origin main
多人协作的工作模式通常是这样:
- 首先,可以试图用
git push origin推送自己的修改; - 如果推送失败,则是远程分支比你的本地更新,需要先用
git pull尝试合并; - 如果合并有冲突,则解决冲突,并在本地提交;
 - 没有冲突或者解决掉冲突后,再用
git push origin推送就能成功; 如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,使用命令git branch --set-upstream-to=origin/main [branchname] 
7. 标签管理(git tag)
在 Git 中,Tag(标签)用于给某个提交打上一个静态的标识,通常用于标记版本发布点(如 v1.0.0)。与分支不同的是,标签一旦创建不会随后续提交而移动。
- 轻量标签(Lightweight Tag):相当于对某个提交的一个固定引用,仅包含提交对象的 SHA-1 值。
 - 注解标签(Annotated Tag):保存在 Git 数据库中完整的对象,包含标签的元数据(标签名、作者、日期、附注),并可选地进行 GPG 签名。
 
7.1 创建标签
# 为HEAD指向的提交创建一个轻量标签
$ git tag <tag_name>
# 示例
$ git tag v1.0.0
# 指明提交哈希
$ git tag <tag_name> <commit_id>
# 为HEAD指向的提交创建一个带注释的标签
$ git tag -a <tag_name> -m "标签说明文字"
# 示例
$ git tag -a v1.0.0 -m "Release version 1.0.0"
7.2 查看标签
# 列出本地所有标签
$ git tag
# 按字母顺序显示并筛选关键字
$ git tag -l "v1.*"
# 查看某个标签所指向的提交信息
$ git show <tag_name>
# 示例
$ git show v1.0.0
7.3 删除标签
# 删除本地标签
$ git tag -d <tag_name>
# 示例
$ git tag -d v1.0.0
# 删除远程标签
$ git push origin --delete <tag_name>
# 示例
$ git push origin --delete v1.0.0
7.4 推送标签
# 推送单个标签
$ git push origin <tag_name>
# 示例
$ git push origin v1.0.0
# 推送所有标签
$ git push origin --tags
签名标签(GPG Signature)略,需要安装并配置 GPG,且在 Git 中配置 user.signingkey
8. Git 自定义
8.1 忽略特殊文件
有些时候,用户必须把某些文件放到 Git 工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件等。在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
不需要从头写.gitignore文件,GitHub 已经为用户准备了各种配置文件,只需要组合一下便可以使用。所有配置文件可以直接在线浏览:https://github.com/github/gitignore
忽略文件的原则是:
- 忽略操作系统自动生成的文件,比如缩略图等;
 - 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
 - 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。
 
强制添加忽略的文件:git add -f [filename]
8.2 配置别名
# st表示status
$ git config --global alias.st status
# co表示checkout
$ git config --global alias.co checkout
# ci表示commit
$ git config --global alias.ci commit
# br表示branch
$ git config --global alias.br branch
# last表示最后一次提交信息
$ git config --global alias.last 'log -1'
# unstage表示把暂存区的修改撤销掉
$ git config --global alias.unstage 'reset HEAD'
注意: 配置 Git 的时候,加上
--global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。每个仓库的 Git 配置文件都放在.git/config文件中。