From dfead2034eb2ab5fc153b40dcb7996a0104e3be6 Mon Sep 17 00:00:00 2001 From: yx-ren Date: Sat, 30 Nov 2019 15:01:40 +0800 Subject: [PATCH] expand rebase cmd and add clean, bundle cmd --- tools/git.txt | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/tools/git.txt b/tools/git.txt index 0b617d3..a114669 100644 --- a/tools/git.txt +++ b/tools/git.txt @@ -46,6 +46,8 @@ git reflog git log -n 最近n条的提交历史 git log -n 分支branch_name最近n条的提交历史 git log --stat 历次commit的文件变化 +git log --shortstat 对比--stat只显示最后的总文件和行数变化统计(n file changed, n insertions(+), n deletion(-)) +git log --name-status 显示新增、修改、删除的文件清单 git log lhs_hash..rhs_hash 对比两次commit的变化(增删的主语为lhs, 如git log HEAD~2..HEAD == git log HEAD -3) git log -p 历次commit的内容增删 git log -p -W 历次commit的内容增删, 同时显示变更内容的上下文 @@ -58,10 +60,28 @@ git log --decorate 对提交历史关联相关引用, 如tag, 本 git log --oneline --graph --decorate 拼接一下, 树形化显示历史 git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen%ai(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit 同上, 建议alais保存 +git log --pretty=format 常用的选项(摘自progit_v2.1.9) +%H 提交对象(commit)的完整哈希字串 +%h 提交对象的简短哈希字串 +%T 树对象(tree)的完整哈希字串 +%t 树对象的简短哈希字串 +%P 父对象(parent)的完整哈希字串 +%p 父对象的简短哈希字串 +%an 作者(author)的名字 +%ae 作者的电子邮件地址 +%ad 作者修订日期(可以用 --date= 选项定制格式) +%ar 作者修订日期,按多久以前的方式显示 +%cn 提交者(committer)的名字 +%ce 提交者的电子邮件地址 +%cd 提交日期 +%cr 提交日期,按多久以前的方式显示 +%s 提交说明 + git log --since --after 显示时间之后的提交 git log --until --before 显示时间之前的提交 git --author 显示指定作者的提交 git --committer 显示指定committer的提交(注:committer不一定是author) +git log -S [keyword] 仅显示添加或移除了某个关键字的提交(某些场景比单独git log -p | grep [keyword] 好用很多) git log origin/b3.3/master --author=yx-ren --since="2019-10-01" --before="2019-11-01" 查看某作者在某发布版本最近一个月的提交, 常见于线上背锅 git log origin/b3.0/master --author=some_leave --since="1 month ago" 查看某刚离职同事过去一个月的提交, 常见于背锅 git log --since=1.weeks 过去一周的提交(写周报的时候可以看看我这一周干了啥) @@ -93,6 +113,14 @@ git rm/add git commit -m "remove " 删除版本库中的:删除工作区文件后,继续删除版本库中相应的文件 git checkout -- 根据版本库中的恢复工作区 +############################################################################## +# 清理工作区未track也未ignore的文件或文件夹(如各种临时.swp, .patch文件等) +############################################################################## +git clean -i #交互式清理, 不常用 +git clean -n #查看清理文件列表(不包括文件夹), 不执行实际清理动作 +git clean -n -d #查看清理文件列表(包括文件夹), 不执行实际清理动作 +git clean -f #清理所有未track文件 +git clean -df #清理所有未track文件和文件夹, 常用, 但使用前确保新增加的文件或文件夹已add, 否则新创建的文件或者文件夹也会被强制删除 ############################################################################## # 关联GitHub远程仓库(本地到远程) @@ -204,6 +232,124 @@ git push origin :refs/tags/ 删除远程标签(先删除本地标 # rebase 在日常中常用功能主要是两个, 多人协同开发定期rebase master以及压缩某分支多个commit git rebase master 常见于多人开发, 每个开发人员从master checkout出自己的分支, 开发一段时间后提交至master之前最好rebase一下, 防止冲突, 就算真有冲突在本地解决好过强制提交, 开发流程中尽量保证master的干净整洁 + +举个例子: +master分支上有三个提交C1, C2, C3 +某一时刻usr1在C3的master分支上checkout出新的分支, 用于开发服务端支持ipv6新特性, 并提交了C4, C5 +git checkout -b ipv6_support +...... +git commit -m C4 +...... +git commit -m C5 +此时提交状态如下所示 + (origin/master branch) + | +C1 <- C2 <- C3 + \ + \ + \ + C4 <- C5 + | + (ipv6_support branch) + +某同事usr2修改了master上的内存泄漏错误, 并提交了C6, C7, C8三个commit, 然后直接推送origin/master(假设这个期间无其他人推新内容到master) +此时提交状态如下所示 + (origin/usr2/fix_mem_leak branch) + | +C1 <- C2 <- C3 <- C6 <- C7 <- C8 + \ | + \ (origin/master branch) + \ + C4 <- C5 + | + (ipv6_support branch) + +如果此时usr1希望将ipv6的新特性提交至master, 那么在其直接push origin master时会提示master需要合并分支ipv6_support +虽然C4, C5的改动内容完全独立于C6, C7, C8的改动 +但git仍会抓取C5和C8的提交并产生一个新的C9 commit(因两者分支的base不同), 如下图所示 +C1 <- C2 <- C3 <- C6 <- C7 <- C8 + \ \ + \ \ + \ \ + C4 <- C5 <------ C9 + +如果是为了保证master提交记录的"干净完整" +或者是某分支不着急提交, 仍需要更多的测试与开发, 但又不想分支开发周期结束后"偏离"当初checkout的master分支太久远(容易造成更多的冲突) +可以考虑(定期)利用rebase来进行变基 +即上面提到过的多人协同开发, 定期rebase master是个好习惯 +git checkout ipv6_support +git rebase master +结果提交状态如下所示 + (origin/master origin/usr2/fix_mem_leak branch) + | +C1 <- C2 <- C3 <- C6 <- C7 <- C8 + \ + \ + \ + C4' <- C5' + | + (ipv6_support branch) +这种rebase在功能上类似将某分支所有的改动做成多个patch并依次打在指定的新base上 +此时再提交master就不会产生抓取效果, 会将C4'和C5'直接提交至master, 即can be fast-forwarded, 同时也保证了master提交记录的整洁性 +(注: 虽然C4'和C5'的内容和C4, C5完全一致, 但两者base不同, commit hash code也完全不同) + +git rebase --noto #重放, 用于变基在分支branch_lhs中而不在branch_rhs中的commit +#某项目状态分支如下所示, 其中Cn的数字代表提交时间顺 +# T1 某员工urs1从C2(master分支)checkout出一个新的分支用于开发某基础公共组件功能 +# T2 员工usr1开发完毕提交C3, 然后继续在该分支上(或checkout -b server)开发服务端相关功能, 并提交C4 +# T3 master分支有更新, 其他同事usr2提交了C5, C6并推送到了origin master +# T4 员工usr1从server分支切回到C3公共基础的提交, 并创建新分支client, 用于开发客户端功能, 并提交C8, C9 +# T5 员工usr1从client分支切回到server分支继续开发服务端功能, 并提交C10 + (master branch) + | +C1 <- C2 <- C5 <- C6 + \ + \ + \ + C3 <- C4 <- C10 + \ | + \ (server branch) + \ + C8 <- C9 + | + (client branch) + +# 此时该员工希望将客户端相关的功能合并到主分支并发布,但暂时并不想合并 server 中的修改,因为它们还需要经 +# 过更全面的测试。 这时可以使用 git rebase 命令的 --onto 选项,选中在 client 分支里但不在 +# server 分支里的修改(即 C8 和 C9),将它们在 master 分支上重放: + +git rebase --noto client server +# 得到如下图所示的提交状态 +# 注:其中C3', C8', C9'与C3, C8, C9的提交内容完全一样, 但是hash id是完全不同的 + (master branch)(client branch) + | | +C1 <- C2 <- C5 <- C6 <- C8' <- C9' + \ + \ + \ + C3 <- C4 <- C10 + \ | + \ (server branch) + \ + [#####disable######] + [ C8 <- C9 ] + [ | ] + [ (client branch) ] + +#can be fast-forwarded +git checkout master +git merge client +# 提交后分支状态如下 + (client branch) + | +C1 <- C2 <- C5 <- C6 <- C3' <- C8' <- C9' + \ | + \ (master branch) + \ + C3 <- C4 <- C10 + | + (server branch) + git rebase -i HEAD~n 压缩当前分支的n个commit并合并为1个commit, 常见第一行为pick, 剩下的n-1行为squash git rebase --abort # rebase过程中发生错误, 可以利用该命令终止整个rebase过程 @@ -238,6 +384,27 @@ git am --resolved #解决冲突后, 可以执行该命 ############################################################################## +############################################################################## +# bundle(打包) +############################################################################## +# 该命令会将git工程打包, 默认情况下会打包所有commit记录和track的文件 +# 不同于简单粗暴tar.gz打包整个文件夹, bundle只打包那些push过的记录 +# 如某git工程下存在.build构建后的目录, 而.gitignore又忽略了该文件夹 +# 如果利用tar.gz打包则会将那些忽略的文件文件夹一并打包, 可能会造成压缩包极大的臃肿 +# 而又不想仅仅为了打个包就删除整个build目录(如重新build时间成本太大) +# 那么就可以使用bundle进行打包, 该命令只打包track过的文件 +# 并且像url那样直接调用git clone来重建 +git bundle create awesome-cheatsheets.bundle HEAD master #打包重建master分支的所有数据 +git clone awesome-cheatsheets.bundle # 重建工程 + +# bundle也可以打包指定的区间, 至于提交区间有多种表示方式 +git bundle create awesome-cheatsheets.bundle HEAD~10 +git bundle create awesome-cheatsheets.bundle HEAD~10..HEAD +git bundle create awesome-cheatsheets.bundle lhs_commit_md5..rhs_commit_md5 +git bundle create awesome-cheatsheets.bundle origin/master..master +git bundle create awesome-cheatsheets.bundle master ^origin/master + + ############################################################################## # 使用GitHub ############################################################################## @@ -277,4 +444,5 @@ git config [--global] alias. '' 为所有工作区/当 # References ############################################################################## https://www.liaoxuefeng.com/wiki/896043488029600 +https://git-scm.com/book/en/v2