文章目录
前言
git的常规用法各位应该已经熟知了,这里讲的是使用git来维护历史。在漫长的开发过程中我们会面临各种情况,bug修改、打补丁等,这个时候仓库可能已经积累了上千上万条提交历史,这样会使得维护难度大大增加,所幸git提供了一些命令帮助我们进行历史维护。
需要注意的是,使用这些命令是 十分危险
的,可能导致其他开发者记录丢失,因为这些命令会改变提交历史的hash校验值,有些是部分提交,有些是整一条分支,还有些是所有分支,修改完只能强推到主仓,所以一定要慎用
。
文章只讲了我目前了解到的内容,后续再更新
git rebase
git rebase可以用于修改提交历史
有些是按Esc,再按:wq退出
git rebase也可以用于合并分支,和git merge有点像,网上搜到的大多是关于这方面的内容,这里就不赘述了,放个链接https://blog.csdn.net/weixin_42310154/article/details/119004977
git filter-branch
git filter-branch使用的时候会弹出下面的信息,这是因为这条命令有些坑,不好用,git官方建议使用git filter-repo来替代,所以能不用尽量不用。为了便于阅读,我会将条信息删除。
$ git filter-branch -f --msg-filter 'sed "s/add b/Hello world!/g"'
WARNING: git-filter-branch has a glut of gotchas generating mangled history
rewrites. Hit Ctrl-C before proceeding to abort, then use an
alternative filtering tool such as 'git filter-repo'
(https://github.com/newren/git-filter-repo/) instead. See the
filter-branch manual page for more details; to squelch this warning,
set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...
git filter-branch修改的是整一个分支所有的历史,而不是单纯在当前提交记录或者某个记录做出修改。
在使用过git filter-branch时,git会备份修改之前的历史,如果你想要再执行命令时会失败,需要使用 -f
参数
如果你想全分支修改,也就是同时修改本地仓里所有的分支,可以使用-- -all
参数
filter
在匹配到filter后会去执行其后的command命令,相当于执行了eval命令。
若command返回值为非0,则,整个操作(branch ?filter? )会被中止
注意,如果修改commit成功,commit ID会发生变化
如果没有指定filter,commit会被重新提交但通常不会改变
–msg-filter
–msg-filter用于修改提交记录的文字说明内容,也就是git commit -m "文字说明"里双引号的内容
示例如下
$ git log --oneline #修改前的log
e0acc4f (HEAD -> master) add c
90a9a50 add b
e0b2c25 add a
$ git filter-branch -f --msg-filter 'sed "s/add b/Hello world!/g"' #修改命令
Rewrite e0acc4fe16ac6f96acdb8f5b60a0a23bbffa43e3 (3/3) (0 seconds passed, remaining 0 predicted)
Ref 'refs/heads/master' was rewritten
$ git log --oneline #修改后的log
12aab45 (HEAD -> master) add c
9df7123 Hello world!
e0b2c25 add a
在这里–msg-filter后面跟的是linux指令sed,其作用替换文本内容。整一条git filter-branch命令会查找当前分支所有提交信息,将add b替换成Hello World。
注意修改之后commit ID发生了变化。
–env-filter
用于修改作者/提交者的姓名、邮箱、时间等环境变量
git提供的环境变量如下
GIT_COMMIT,
GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE,
GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, and GIT_COMMITTER_DATE
如果你想用作者的信息来隐藏提交者的日期、姓名和邮箱可用以下命令。需要注意的是,提交者的信息只有在git主仓才能看到,使用git log是看不到的。
git filter-branch --env-filter '
export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"
export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"'
–tree-filter
–tree-filter用于重写tree,也可以理解成修改历史里的文件
示例:
$ ls #查看仓库文件
a b c
$ git log --oneline #查看log
12aab45 (HEAD -> master) add c
9df7123 Hello world!
e0b2c25 add a
$ git filter-branch -f --tree-filter 'touch newfile' HEAD #新增一个文件newfile
$ ls #查看仓库文件变化,多了newfile
a b c newfile
$ git status #查看仓库状态,无变化
On branch master
nothing to commit, working tree clean
$ git log --oneline #查看log变化,ID变了
19f0c57 (HEAD -> master) add c
4299bac Hello world!
633f6cc add a
zetao.zhang@ott13366:~/test$ git checkout HEAD^ #切换到上一个提交记录
zetao.zhang@ott13366:~/test$ ls #查看文件变化,c消失了,newfile还在
a b newfile
$ git status #查看仓库状态,newfile无变化
HEAD detached at 4299bac
nothing to commit, working tree clean
–index-filter
–index-filter的功能和–tree-filter一样,但比–tree-filter更快,除此之外暂未找到其他的区别。
–prune-empty
–prune-empty会清除那些空的失去联系的历史记录
$ git log --oneline #查看log
19f0c57 (HEAD -> master) add c
4299bac Hello world!
633f6cc add a
$ ls #查看文件
a b c newfile
$ git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch c' #删除c不带--prune-empty
$ ls #查看文件,少了c
a b newfile
$ git log --oneline #查看log,ID变了
21e7f3a (HEAD -> master) add c
4299bac Hello world!
633f6cc add a
$ git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch c' --prune-empty #带上--prune-empty再删一次
$ git log --oneline #查看log,只剩下两条
4299bac (HEAD -> master) Hello world!
633f6cc add a
git filter-repo
使用git filter-repo命令需要自行下载该工具,默认是不提供的
–replace-text
–replace-text参数用于替换文件里的内容,使用方式如下。
由于该命令会修改所有历史里的所有文件,所以在修改时请确保修改内容唯一
git filter-repo --replace-text <(echo "查找内容==>替换内容") --force
示例:
$ git log --oneline #查看log
e7780c7 (HEAD -> master) update a
4299bac Hello world!
633f6cc add a
$ cat a #查看a内容
add something in a
$ git filter-repo --replace-text <(echo "add something in a==>something changed") --force #修改文件内容
$ cat a #查看a内容,改变了
something changed
$ git log --oneline
4cd8a5a (HEAD -> master) update a
4299bac Hello world!
633f6cc add a
参考资料
git-filter-branch 英文手册 https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-branch.html
git-filter-repo 英文手册 https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html