git 入门到精通
未完待续..
1 配置
1.1 修改配置
1.2 config的作用域
1.3 显示配置
1.4 我的配置
[user]
name = yourusername
email = youremail
[core]
trustctime = false
editor = vim
filemode = false
autocrlf = false
# 如果是true ,非ASCII 字符会用八进制进行转义
# 现在终端都支持输出其他字符了,所以取消
quotepath = false
[alias]
last = log -1 --stat
cp = cherry-pick
co = checkout
cl = clone
ci = commit
st = status -sb
br = branch
unstage = reset HEAD --
dc = diff --cached
lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %Cblue<%an>%Creset' --abbrev-commit --date=relative
pull = pull --ff-only
df = difftool
mg = mergetool
[merge]
tool = vimdiff
[diff]
tool = vimdiff
[difftool]
prompt = false1.5 git clone慢的解决方法
这样你git clone https://github.com/xx/yy 就会变成 git clone https://ghproxy.com/https://github.com/xx/yy
git config --global url."https://ghproxy.com/https://github.com/".insteadOf https://github.com/取消url insteadOf
git config --global --unset url."https://ghproxy.com/https://github.com/".insteadOf使用http代理
使用socks5代理
1.6 .gitignore
从 github1 上下载 对应语言的.gitignore 文件
1.6.1 保留文件夹,忽略里面的内容
在目标文件夹内单独建一个.gitignore文件,而不是写在根目录的.gitignore里
或者 目标文件夹data里面 添加一个.gitkeep 总的.gitignore
1.6.2 查看文件是否符合.gitignore规则
2 开发人员一般步骤
1.git clone 下公司代码仓库
2.以dev或其他开发中的主分支比如WIP(用公司可能用这个分支名字)或者其他 v1.0 这种 创建一个分支进行开发 注意一个功能,或一次bug修复就用一个分支.
3.写代码, git add,commit, 至少每天下班前 git commit 一次, 功能开发完毕 合并前,可以随意commit,随意的推送该分支到远程
4.提交pull request 阶段
将你的commit 合并成一个commit 这个commit_id 是你 git co -b fix/xyz 分支时的最新commit
合并现在最新的dev代码到你的分支
# 先拉取最新的dev代码到本地dev
git pull origin dev:dev
# 本地合并来自 dev的最新代码 不要用merge
# 就相当于你在最新代码的dev分支的基础上进行开发,merge 完全没必要
git rebase dev* 99a02ef - (HEAD -> fix/one) Merge branch 'wip' into fix/one
|\
| * e33481e - (wip) Merge branch 'fix/hello' into wip
| |\
| | * be69a6e - (origin/fix/hello, fix/hello) fix b.txt add hello
| |/
* / 95d6da4 - fix c.txt add one
|/
* 123ffca - add c.txt
* 5721887 - add b.txt
* b8172ad - add a.txt
* 128d312 - (origin/master, origin/HEAD, master) readme3 常用命令
3.1 clone
仅仅为了使用那个仓库
# 只下载最近一个commit, 我们下载最新的代码就行了
git clone --depth=1 https://github.com/vuejs/vuepress.git
# --branch 分支名: 对比 git clone ,checkout 指定的分支, 其他分支还是会拉取
git clone --branch dev https://github.com/vuejs/vuepress.git
# 只下载指定分支 需要再加上 --single-branch ,其他分支不会拉取
git clone --branch dev --single-branch https://github.com/vuejs/vuepress.git3.2 pull
- 当合并的分支为当前分支的后代时, 会自动执行 –ff (Fast-forward)模式,
- 如果不是后代则执行 –no-ff (non-Fast-forward)合并模式
在任何情况下都会创建新的commit
只会按照 Fast-forward 模式进行合并,如果不是当前分支的直接后代,则会拒绝合并请求并退出
3.3 remote 仓库
# 查看远程仓库信息
git remote -vv
# 添加 新的远程仓库,你可以添加多个远程仓库
git remote add new_origin git@github.com:llibeohs/llibeohs.github.io.git
# 直接修改远程仓库地址
git remote set-url origin git@.../test.git
# 删除
git remote rm origin本地删除已经不存在的远程分支, 别人提交的远程分支,你 pull过, 然后别人删除了远程分支,这个时候你本地还保留着,想要删除
3.4 branch
# 推送本地分支到远程分支,这个远程分支名与你的本地分支同名
git push origin your_branch
# :左边是本地分支 右边是远程分支名
git push origin dev:dev
# 将你新建的本地分支dev与远程分支关联起来
# 这样 你就可以直接 git push, 不需要每次都 git push origin dev
git br -u origin/dev dev
# 可以看到关联信息
git br -vv
#dev2 a950611 up <--- 无关联
#master a950611 [origin/master: ahead 3] up<---- 有关联
# 第一次push 时直接关联远程分支
git push -u origin dev
# 该方式直接从远程分支origin/dev 创建本地分支dev,并切换到 该本地分支dev,
# 这个时候 已经互相关联上了,可直接git pull/push
git co -b dev origin/dev3.5 checkout (co)
3.5.1 co –
3.5.2 孤儿分支
3.6 add
3.7 unstage
3.8 commit 注释修改
修改之前的commit的注释信息
git lg
* df6b55b - (HEAD -> master) modify:d
* 565bd5a - modify c.txt
* b50b285 - stg3yy
* 23fd353 - stg2
* 4164370 - stg1
# 比如你要修改23fd353 的msg,那么你需要
git rebase -i 4164370 #(你要修改的commit的上一个commit)
# 会弹出一个窗口
# 注释也说的很明白,
# 这里比如我们要修改2个commit的msg,我们将前面默认的pick 修改为r,
# r, reword = use commit, but edit the commit message
# 其他不要变的 就还是pick
# :wq 保存退出,会跳出另外一个窗口
r 23fd353 stg2
r b50b285 stg3yy
pick 565bd5a modify c.txt
pick df6b55b modify:d3.9 cherry-pick (cp)
将任意分支上的某几个提交,应用到当前分支上, 相当于在当前分支上你做了这些修改
3.10 clean 删除不在工作区的文件
# -n = --dry-run
# 表示先看看会删除什么 ,删除不在工作区的文件. 就是还从没git add过的
# 只会看文件
git clean -n
# -d 会看不在工作区 的文件(默认就会看的)和文件夹
git clean -n -d
# 会提示你 clean.requireForce defaults to true and neither -i, -n, nor -f given; refusing to clean
git clean
# 执行删除操作 , 需要-f
git clean -f
# -d 文件夹也删除
git clean -f -d
# -x 在.gitignore 文件里的 也会删除,默认不会删除
git clean -f -d -x3.11 rm
3.12 diff 比较
# 更旧的放前面,新的放后面,想看commit2 相对commit1做了哪些更改
# 可以是不同的分支的commit id哦
git diff commit1 commit2 filename
#查看将要推送的内容, (比较本地的dev分支对 远程dev做了哪些修改)
git diff origin/dev..dev
# 实际与 git diff HEAD~~ HEAD 一样
git diff HEAD~~..HEAD~
# 比较tmp分支和master分支 a.txt文件的区别
git diff tmp master -- a.txt
# 直接用commit_id 来比较 也是一样的
# 因为实际上分支名比较的原理就是 就是因为分支名指向的就是该分支最新的一次提交,还是commit_id
git diff tmp_commit_id master_commit_id -- a.txt3.13 冲突
一般情况下 会看到 上面 一个是我们分支的版本 一个是你想要merge的分支的版本
oyo 是我们的版本的修改
omo 是别人的版本的修改
可以通过设置 merge.conflictstyle 选项为 diff3 来做为以后合并冲突的默认选项
git config --global merge.conflictstyle diff3
merge 是默认选项, diff3 就会生成3方内容来对比
增加原始版本
ooo是原来的情况
3.14 log
# 查看项目的提交记录
git lg
git lg 文件名 #(查看该文件的提交记录 log)
git lg commit_id #(查看这个commit_id 以及之前的提交记录log)
#-p 按补丁格式显示每个更新之间的差异。
# 会显示提交的内容
git lg -p commit_id # (查看这个commit_id 以及之前所有的提交内容)
git lg -p #(查看提交内容 相比git lg, 多了内容的查看)
git lg -p + 文件名 #(可查看该文件以前每一次commit的修改内容)
git lg -p -1 + 文件名 #(只查看该文件当前这一次的commit内容)
git lg -p dev..fix/one # 查看你的分支相对于本地dev分支做了哪些修改
git lg -p origin/master..HEAD # 当前分支最新代码对与远程master分支做了哪些修改3.15 rebase
3.16 shortlog 显示发布简报
可用于显示这次发布,更新了哪些东西
3.17 blame
3.18 bundle 打包
# 打包整个master 分支
git bundle create x.repo HEAD master
# 根据打的包 clone 仓库 到 tmp_dir 目录
git clone x.repo tmp_dir
#打包几个提交
#打包当前我们新增加的几个提交,本地fix/one分支相对于远程提交了哪些
git bundle create ../new_commit.bundle origin/dev..fix/one
# 切换到dev分支,拉取最新,然后校验看是否能更新ok
git co dev
git pull
git bundle verify ../new_commit.bundle
# 将fix/one里的提交 ,导入到wip 分支
git pull ../new_commit.bundle fix/one:wip3.19 tag
4 进阶技巧
4.1 hook2
4.1.1 基础
4.1.2 pre-commit framework
todo…
4.2 CHANGELOG
4.2.1 git cliff3
TODO
生成changelog 工具
cliff.toml 修改其中的postprocessors 配置
4.2.2 git-chglog4
4.3 子模块
4.3.1 subtree
4.3.2 submodule
4.3.2.1 修改.gitmodules仓库url后需要的操作
[submodule "themes/docsy"]
path = themes/docsy
url = https://github.com/google/docsy.git
branch = v0.2.0后来这个地址变更了,拉取最新, .gitmodules 是变更了
.gitmodules 变更后的结果
4.4 git filter-repo
比如commit了一个可执行文件,推送到了远程,然后下个commit你将它删除,推送,实际上这个文件还是存在的. 如何彻底删除它?
安装5
# 只保留README.md文件 和 guides/目录和 tools/releases目录 ,相对于根目录位置的文件
git filter-repo --path README.md --path guides/ --path tools/releases
# 与上面刚好相反, 只删除这几个 东西 , 相对于根目录位置的文件
git filter-repo --path README.md --path guides/ --path tools/releases --invert-paths
#--path-glob '*.DS_Store' 指定这个的话 , 相比path,这个会 包含这类foo.DS_Store or bar/baz.DS_Store
#--path 基于根目录的
#使用这个命令后, 不需要再 清理reflog 和original里的东西 (git filter-branch 这个官方的需要这么做), 因为已经帮你做了
#直接
git push -f --all
git push -f --tags4.4.1 实际仓库瘦身
#执行命令, 会进行压缩打包, 在 .git/objects/pack 目录下生成一个pack文件,
# objects/ 原本好多的文件夹都不见了. 都压缩打包到了这里
git gc
#可以看到pack打包的文件里 具体是什么文件
git verify-pack -v .git/objects/pack/*.idx
#查看当前所有的文件. 多次commit 都会显示哦
git rev-list --objects --all
#-k 3 对第三列的字段进行排序. -n 表示用数值排序
git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n
#找到占用空间比较大的文件名
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -15 | awk '{print$1}')"
#下方命令中的 path/to/large/files 是大文件所在的路径,千万不要弄错!
git filter-branch --tree-filter 'rm -f path/to/large/files' --tag-name-filter cat -- --all
#如果提示
Cannot create a new backup.
A previous backup already exists in refs/original/
Force overwriting the backup with -f
就
git filter-branch -f --tree-filter 'rm -f path/to/large/files' --tag-name-filter cat -- --all
# 运行后
提示 所有分支都重写了. 所有分支里的这个文件 都没有了哦
Ref 'refs/heads/master' was rewritten
Ref 'refs/heads/x' was rewritten
Ref 'refs/remotes/origin/master' was rewritten
Ref 'refs/remotes/origin/x' was rewritten
# 提交
git push origin --tags --force
git push origin --all --force