git 本质
存在一个 对象池 object
stage, branch0, branch1, … 都是一些指针目录树,树上的每个结点会指向对象池里的一个对象【一个分支就是一个目录树,树上结点就是指向某个对象的指针】
HEAD 指向的是本地分支库中当前工作的分支(就是记录当前目录树的 git_pos)
origin 中就是远程分支库在本地的副本 origin/main 就是一个副本目录树

1 Git 基本命令

基本配置命令
config --global user.name # 配置文件在 ~/.gitconfig 下面
1
2
3
4
git config --global user.email
git init
git add
git commit -m ""
状态查看指令
  • git status
    • 查看当前所处的分支、各个文件的状态(在工作区、暂存区…) 和基本信息
  • git reflog 查看之前的版本
    • git reflog -n 数量 可以指定查看数目的版本
  • git log 可以查看详细的版本信息,但是建议使用 git log --reverse --oneline
相对引用
  • 一般而言使用 哈希值的前四位可以识别一个提交
    • 但是这样不方便,每次都要git reflog 来查找
  • 使用相对引用操作符
    • ~ ^ 在某个位置标记后面
    • ~3 表示回退三次
    • ^2 表示选择多parent 的非直线parent
    • 单次使用 ^ 表示回退一次
  • git tag tag_name git_pos 勤劳打tag,固定某个位置作为某个版本
    • git describe 可以根据 最近的tag 返回描述

2 单线操作指令

文件恢复
  • git restore file 从暂存区获取并回滚文件
  • 用暂存目录树切换掉当前工作区, git checkout .
  • git reset 版本号 这里的版本号可以用 git reflog 查看
    • hard 是 HEAD指向,工作区和暂存区都重置
    • mixed 是仅仅 HEAD指向和暂存区重置
    • soft 是仅仅 HEAD 指向重置
撤销变更
  • git reset git_pos 把HEAD重置到某个版本
  • git revert branch_name不一样
    • 会创建一个新的提交,而这次提交的内容其实只是为了说明回撤到了某个版本
    • 说明转回某个版本了,但是中间的历史没有覆盖
    • 目的在于把代码库的撤销更改能够应用到远程库,使大家能共享(如果不这样的话,历史会不一致,导致无法提交)

3 分支操作

创建、删除展示分支
  • git checkout -b new-feature 创建一个 叫做 new-feature 的新分支(并且立马切换过去)
  • git branch -d 名字 可以删除指定名字的分支
  • git branch 展示分支
跳转与分支操作
  • 切换分支使用 git checkout 分支名
  • 用git_pos指定的提交版本切换掉工作区和暂存区 git checkout git_pos .
    • 如果是单个文件使用 git checkout git_pos -- <filename>
  • 分离 HEAD
    • git checkout git_pos 使得 HEAD 指向回退到这个版本的代码
  • git branch -f main git_pos 把main 分支移动到hash_pos 指定的位置,main 分支从这里开始重新提交
  • git branch -m master main move/rename 重命名
分支整理
  • git merge 其他分支 把其他分支的内容合并到当前分支
  • git rebase a b 利用 b 操作 a 分支(把 b 上提交变基到a上,在a上创建一系列提交)
    • 会有一个清晰的提交线,提交历史不会打结
  • git cherry-pick git_pos1 git_pos2 … 挑选 patch 在当前分支下
    • 尤其适用于某个测试分支下,先前写了很多版本的printf 的代码,只需要最后一个版本的改动,直接只pick 最后一个版本的改动
  • git rebase -i main 在main分支所在位置列出接下来可能的版本,手动拖拽 patch 调整位置,选择是否omit,或者

4 Git 远程操作

远程仓库和本地库

git push -u origin main推送
git fetch origin拉取远程仓库内容到本地

远程仓库和工作区

git pull origin main = git fetch origin + git merge origin/main

设置和修改远程库

git remote add origin 地址 添加远程库
git remote set-url origin 地址 修改远程库
git remote rm origin 删除远程库
git remote -v 查看远程库信息

具体远程操作
  • 如果直接操作 origin/main 会直接变成分离头模式
    • 应为origin/main 其实是和远程最近一次拉取保持同步的,强行操作会导致版本历史无法对应
  • 拉取、整合代码
    • git fetch 把所有远程分支的代码拉取下来
      • git fetch origin main 只把main 分支的代码拉取下来
      • 参数可以使用 <source>:<destination> 指定,其中 source 可以是在远程的 git_pos (把具体某个版本的代码拉取到固定的分支
      • 如果 git fetch origin :bar 会在本地新建 bar 分支
    • git pull 把默认追踪的分支代码拉取下来并merge
      • 把更改合并到当前分支 ≈ git fetch + git merge(一定是合并的HEAD指向的分支,而不是main 分支)
      • git pull -- rebase 采用变基的方式更新主枝代码(把origin/main 的代码变基到主枝
  • 推送代码
    • git push 完成默认跟踪分支的代码的推送
      • 加入参数 git push origin <source>:<destination> 其中 source 可以是任何git 能识别的版本标识,可以把本地任何一个版本的代码推动过去,destination 表示远程的某个分支
      • 推送的时候需要保证 和远程分支的历史是一致的,如果不一致需要先 git pull 或者 git pull – rebase 进行拉取整合之后再push
      • 如果使用 git push origin :foo 会删除远程的foo分支
      • git push -u 选项表示 set-upstream 就是设置分支跟踪的远程分支
  • 变更追踪远程分支的分支
    • git checkout -b foo o/main 新建一个分支foo 默认让foo 跟踪远程的 main 分支
    • git branch -u o/main foo 如果 foo 已经在使用了可以用branch命令,并追踪远程分支 origin/main

5 使用建议

  • 切换版本 git checkout
  • 创建分支 git checkout -b name 如果你有很多个想法,直接开多个分支实现就好了,然后在 readme 文件中写好自己的想法的实现步骤,这样就不用建立很多个不同名字的库了,真的很难管理!而且如果data 这样的目录没有被管理到,就是所有分支共享的,这样数据使用也很方便
  • 回溯版本
    • 不保留工作区的内容并且不覆盖之前的历史,只是做替换:git checkout git_pos .
    • 不保留工作区的内容,逻辑上将要覆盖掉reset到的版本之后的提交的历史(但是在 reflog 中仍然可以找到) 从reset的版本之后继续给出新的提交 git reset --hard git_pos
    • 保留工作区内容,但是暂存区改写,并且从 reset版本开始重新提交 git reset --mixed git_pos
    • 保留工作区和暂存区的内容,仅仅从 reset 到的版本重新开始提交 git reset -soft git_pos
  • git fetch origin, 先比对,之后 git merge origin/main 合并,在很有信心需要直接合并的时候再使用 git pull origin main
  • 直接使用可视化工具查看 git 分支和提交信息
  • 添加远程库 git remote add origin 地址