Git权威指南 阅读

发布时间 2023-07-05 00:15:43作者: Geraltz'Rivia

Git权威指南

git

版本控制软件,文章中把这种分布式的版本控制软件与其前身Subversion做比较,svn我没有使用过;原来对git的使用也基本上只局限于常用的指令,比如commit、branch、checkout、push、pull等,而且基本都是比较基础的用法,对于命令的参数也不太熟悉,通过阅读书籍以及实际操作记录下新的命令。

命令记录

git --version 

// 初始化配置
git config --global user.name "username"
git config --global user.email user@email.com

// 设置别名(应该是满足svn用户习惯
sudo git config --system alias.st status
sudo git config --system alias.ci commit

// 初始化仓库
git init <repo_name>

// git add命令可以把修改的内容加入暂存区
git add -u // 添加所有修改的文件
git add -A // 添加本地新增或者删除的文件
git add -p // 预览修改并且有选择的添加

git grep // 查找纳入管理的文件内容

git rev-parse --git-dir // 查看版本库.git所在位置
git rev-parse --show-toplevel // 显示工作区根目录
git rev-parse --show-prefix // 显示相对于工作区根目录的相对目录
git rev-parse --show-cdup // 显示从当前目录后退到工作区根目录的深

git config -e // 可以打开当前repo的配置文件修改,也可以提供参数 --global 用户全局配置 --system 系统级配置
git config <section>.<key> // 直接读取对应的参数
git config <section>.<key> <value> // 直接修改对应的参数
git config --unset // 删除配置

git commit --amend --allow-empty --reset-author // amend参数修改上次提交,allow-empty允许没有用户名邮箱,reset-author修改提交的user信息
git clone -l -s -n . ../copy // 把项目clone到本地一份

可以直接通过 man 命令查看帮助,或者等效于 git --help ,默认通过分页器进行输出,在分页器中按 h 可以查看帮助,常用的按键命令:

q:退出

h:查看帮助

空格键向下翻页,b向上翻页

d和u分别向下与向上翻半页;j与k向上与向下翻一行

/pattern 向下寻找pattern匹配的内容

?pattern向上寻找匹配的内容

n或者N表示继续寻找下一个或者上一个

g:跳到第一行;G:跳到最后一行;输入数字加g:跳转到数字行

!:执行命令

奇怪的命令

git format-patch v1..HEAD
git send-email *.patch
git grep

git commit --amend // 对上次commit的信息进行修改
git rebase -i // 修改某次commit的信息

git 暂存区

.git/index 维护着一个虚拟的工作区目录。除了工作区本身的目录,还有版本库中维护的暂存区的目录,以及master分支指向的目录

执行 git reset HEAD 命令时,暂存区的目录会被HEAD替换,工作区不受影响

执行 git remove --cahced 命令时,会从暂存区删除文件,工作区不受影响

执行 git checkout HEAD . 非常危险,会用master分支上全部文件替换掉暂存区以及工作区上的文件,工作区中没有提交的修改以及在暂存区中的修改也会被重置

git 对象

git中的对象(比如提交、树、文件变更)等都会用40位的SHA1哈希值表示,这些对象存储在仓库的 .git 目录下,通过 git log 命令可以查看commit记录信息,比如

// git log --pretty=raw

commit 021449d1080ef26d0a8149d4e6af88209e42d81e

tree 3111d544242fdef3aec4cc4b07b188aa756ba2d9

author chuyuxuan <> 1686041498 +0800

committer chuyuxuan <> 1686041547 +0800

change commit message;commit test

使用 git cat-file -t 命令可以查看对象类型, 使用 git cat-file -p 命令可以查看对象具体内容

查看一个树可以看到这个分支包含的全部文件,这里的每个文件也都是一个git对象,类型是blob,内容就是当时的文件内容,这些对象都存储在 .git/objects 目录下,用对象的前两位做次级目录进行分类

.git/refs 目录保存引用,.git/refs/heads 目录下的引用就是分支.

计算sha值:看看怎么做的

-- git cat-file commit HEAD | wc -c

 200

-- (printf "commit 200\000";git cat-file commit HEAD)| shasum

021449d1080ef26d0a8149d4e6af88209e42d81e -

-- git rev-parse HEAD

021449d1080ef26d0a8149d4e6af88209e42d81e

使用 HEAD 可以表示版本库中的最近一次的提交,使用^ 表示上次的提交,多个父提交可以在 ^后表明数字来指定是哪个父提交

也可以使用<n>来表示祖先提交,HEAD5 等同于 HEAD-^^^^^-

git reset

git reset [-q] [commit] [--] ...

使用在commit状态下 paths中的文件重置当前暂存区的文件,默认commit是HEAD

git reset [--soft|--hard|--mixed|--merge|--keep] [commit]

根据不同的选项对工作区或者暂存区的文件进行重制

git reset -- filename 添加文件的反向操作

What's the difference between git reset --mixed, --soft, and --hard?

git checkout

git checkout [-q] [commit] [--] ...

默认从暂存区进行检出,相当于使用暂存区的修改替换工作区的修改,不改变HEAD

git checkout []

进行切换分支,如果不加branch相当于进行工作区状态检查

git checkout [-m] [[-b|--orphan] new_branch] [<start_point>]

创建并切换到新的分支

git stash

git stash

git stash list

git stash pop [stash]

从某个stash恢复

git stash apply

从stash中恢复,但是保留stash的记录

git stash [save []]

上面git stash的完整版,可以提供信息

git stash drop [stash]

删除一个stash,默认最新

git stash clear

删除所有储存的进度

git rev-list

git blame

查询一个具体文件的各行都是谁先提交的,用于定位问题

git bisect

在各个版本上进行判断,找到最近的坏提交;支持脚本进行自动化判断

git历史穿梭

这部分主要分为几部分,首先说明浏览提交信息(git log)、版本范围的表示方法(git rev-list);

对前一个或者几个提交的变更(悔棋

git commit --amend 或者 git reset --soft

变更某次提交导致后续提交发生变化(改变时间线

git cherry-pick

git rebase

git rebase --onto

先checkout到till

把since..till范围的提交写到一个临时文件中

将当前分支重置到newbase

从保存的临时文件的提交记录中,逐一提交记录

提交遇到已提交过的,跳过;遇到冲突提示用户解决

A-B-C-D-E-F如果想抛弃D提交

git rebase --onto C E^ F 等价于git rebase --onto C D

删除提交的历史记录

希望在tag A前的提交记录都删除,则可以构造一个以A为根提交,在将A之后的提交rebase到新的节点上

创建根提交

git commit-tree

git hash-object

反转提交

git revert

提交之后再反向提交,避免“覆水难收”

git协作

常见的命令 clone push pull

合并时树冲突问题:双方都对文件目录进行了修改,导致合并的时候出现了冲突

解决方案:在遇到冲突时,根绝实际情况解决,一般情况下可以使用git rm移除冲突的文件之一,然后用git add决定保留文件,最后commit

git merge不同的合并策略

git tag 有轻量级的里程碑与完整的里程碑,轻量级的没有commit信息,没有设立里程碑的用户信息

里程碑一旦设立,最好不要随意修改;里程碑的共享必须显式的推送给远端,并且本地与远端存在同名的里程碑,本地不会同步,即使这两个对象不同;可以往远端推送一个空值来删除里程碑。

git branch -m 重命名分支

分支合并的变基操作

普通的merge,在G处merge的时候,需要review3个commit的代码(E,F以及merge的commit)

A - B - C - D - G

\ /

   E ----   F 

使用rebase

在开发分支上 git rebase master

A - B - C - D

\

E - F

这里只有E、F两个commit

执行变基指令时,步骤:先checkout到开发分支(即E F提交在的分支),然后记录提交到临时文件,然后强制切换到master分支(这时候是D)并把提交一一拣选到开发分支上。这时候开发分支上已经包含全部提交了,然后切换到master上merge dev,就能执行fast forward

关于merge与rebase,可以看看 这个文章 ,有动图说明比较详细

git remote

.git/config 文件中有个包含[remote]的配置(随便找的一个repo

[remote "origin"]

url = https://github.com/ossxp-com/gitdemo-commit-tree.git

fetch = +refs/heads/*:refs/remotes/origin/*

fetch会把所有远程分支拿到本地,也可以git remote add添加新的远程版本库

git 协作模型

参考 常见模型