创建仓库

# 创建本地仓库到当前文件夹
git init
# 创建本地仓库到当前文件夹下的子文件夹
git init <子文件>
 
# 拉取远程已存在的仓库到本地(使用远程仓库名)
git clone <远程仓库地>
# 拉取远程已存在的仓库到本地(使用新名字)
git clone <远程仓库地> <新名>

工作区域和文件状态

工作区域:

  • 工作区(Working Directory):.git 所在的目录
  • 暂存区(Staging Area / Index):.git/index
  • 本地仓库(Local Repository):.git/objects

文件状态:

  • 未跟踪(Untrack):新建的文件,没有被 git 管理
  • 未修改(Unmodified):被 git 管理的文件,没有在工作区进行修改
  • 已修改(Modified):被 git 管理的文件,在工作区进行了修改
  • 已暂存(Staged):已添加到暂存区

命令:

  • git status:查看仓库状态
  • git add:添加到暂存区
  • git commit:提交到本地仓库
  • git log:查看仓库提交历史记录
    • --oneline:每条历史记录显示一行

git reset

回退到某个版本,版本是指提交到本地仓库的记录

  • git reset --soft:回退到某一版本,保留到工作区和暂存区
  • git reset --hard:回退到某一版本,丢弃工作区和暂存区
  • git reset --mixed(默认):回退到某一版本,保留工作区,丢弃暂存区

softmixed 基本相似,使用场景是连续提交了多个没有意义的版本,可以回退,合并成一个版本重新提交

hard 的使用场景是真的要放弃某个版本之后的所有提交

git reflog 查看操作记录,使用 git reset --hard 回退到某个操作

git diff

查看三个工作区域之间的差异、不同版本之间的差异、不同分支之间的差异

  • git diff:查看工作区和暂存区之间的差异
  • git diff HEAD:查看工作区+暂存区和版本库(本地仓库)之间的差异
  • git diff --stagedgit diff --cached:查看暂存区和版本库之间的差异
  • git diff <commitHash 1> <commitHash 2>:查看不同版本之间的差异
  • git diff <branchName 1> <branchName 2>:查看不同分支之间的差异

在命令后面还可以写一个或多个文件名,表示只看某些文件的差异

HEAD

  • HEAD:表示当前的所在的提交节点,默认指向当前分支的最新提交节点
  • HEAD^HEAD~HEAD 的前一个提交
  • HEAD^<n>HEAD~<n>HEAD 的前 n 个提交

git rm

  • rm <file>; git add <file>:先从工作区删除文件,再将删除操作添加到暂存区
  • git rm <file>:把文件从工作区和暂存区同时删除
  • git rm --cached <file>:把文件从 暂存区删除,但保留在工作区中
  • git rm -r *:递归删除某个目录下的所有子目录和文件(从工作区和暂存区同时删除)

注意:以上都只是在工作区和暂存区进行操作,记得提交到版本库

.gitignore

应该忽略的文件:

  • 系统或应用自动生成的文件
  • 编译产生的中间文件和结果文件
  • 运行时生成的日志文件、缓存文件、临时文件
  • 涉及身份、密码、口令、密钥等敏感信息的文件
  • 依赖库,如:node_modules

.gitignore 文件匹配规则:

  • 从上到下逐行匹配,每一行表示一个忽略模式
  • 空行或以 # 开头的行会被忽略
    • 空行用于可读性的分割
    • # 表示注释
  • 使用标准的 glob 模式匹配,例如:
    • * 通配任意个字符
    • ? 匹配单个字符
    • [] 表示匹配列表中的单个字符,如:[abc] 表示 a 或 b 或 c
    • [] 中可以使用短中线连接,如:[1-9] 表示 1~9 之间的任意一个数字
    • ** 表示匹配任意的中间目录
    • / 结尾表示目录
    • ! 表示取反

注意:

  • git 不会管理空文件夹,解决方法是在空文件夹下新建一个 .gitkeep 空文件即可
  • .gitignore 忽略之前就提交到版本库中的文件不受 .gitignore 控制,可以使用 git rm --cached <file> 将其从版本库中删除

远程仓库

  • HTTPS 协议:写操作需要验证 github 用户名和密码
    • 2021 年 8 月 13 日以后,github 停止用户名和密码的验证方式
    • 可以用 token 或 web auth 验证
  • SSH 协议:写操作不需要用户名和密码,但需要在 github 上添加 SSH 公钥的配置(推荐:更加安全和方便)
# 进入家目录的 .ssh 目录
cd ~/.ssh
 
# 生成 SSH 密钥对
# -t rsa:指定使用 rsa 协议
#-b 4096:指定生成的大小为 4096
ssh-keygen -t rsa -b 4096
# 过程需要输入文件名称,直接回车则默认生成名称为 id_rsa
 
# 会生成两个密钥文件
id_rsa     # 私钥
id_rsa.pub # 公钥

如果不使用默认名称 id_rsa,则需要在 ~/.ssh 文件夹下创建一个 config 文件,指定 github 使用的密钥:

# github
Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/test
  • git remote add <远程仓库别名> <远程仓库地址>:添加远程仓库(本地仓库与远程仓库关联)
  • git remote -v:添加本地仓库所关联的远程仓库
  • git branch -M <newName>:将当前分支重命名
  • git push -u <远程仓库别名> <本地分支名>:<远程分支名>:将本地分支内容 推送到远程,并关联分支
    • 当本地分支名与远程分支名同名时,可以简写 <远程分支名>:<本地分支名>分支名
  • git pull <远程仓库别名> <远程分支名>:<本地分支名>:拉取远程仓库内容到本地
    • 当本地分支名与远程分支名同名时,可以简写 <远程分支名>:<本地分支名>分支名
    • 一般直接写 git pull 表示拉取默认关联的远程仓库的关联分支

分支

  • git branch:查看所有本地分支(前面带有 * 的是当前所在分支)
  • git branch <新分支名>:基于当前 HEAD 创建一个新分支(不会切换到新分支,而是还在 HEAD
  • git switch <分支名>:切换分支
    • git switch -:切换到上一个分支
  • git checkout <分支名>
    • 切换分支
    • 恢复文件
    • 移动 HEAD
  • git merge <将要被合并的分支>:把将要合并的分支合并到当前分支
  • 删除本地分支:
    • git branch -d <分支名>:删除已合并的本地分支
    • git branch -D <分支名>:强制删除本地分支,无论是否已合并
    • 注意:不能在将要删除的分支执行以上命令(不能把自己举起来)

合并冲突

  • 两个分支没有修改同一个文件的同一处位置:Git 自动合并
  • 两个分支修改了同一个文件的同一处位置:产生冲突

解决方法:

  1. 手动修改冲突文件的内容
  2. 添加到暂存区
  3. 提交到本地仓库

中止合并:git merge --abort

变基

除了 merge 合并分支外,还有一种方法将多个分支整合到一起,那就是:rebase 变基

git rebase <将要变基到的分支>:将当前分支的新提交变基到目标分支

流程:

  1. 找到两个分支的公共祖先
  2. 将当前分支的新提交变基到目标分支
  • merge
    • 优点:不会破坏原分支的提交记录,方便回溯和查看
    • 缺点:会产生额外的提交节点;分支图比较复杂
  • rebase
    • 优点:不会新增额外的提交记录;形成线性历史,非常直观和干净
    • 缺点:会改变提交历史,改变了当前分支 branch out 的节点