Operation,  Other

大型团队协作之 git cherry-pick / amend

大型团队协作之 git cherry-pick / amend

1. 使用 git cherry-pick 增量插入式合并提交

  • 1.1 常用于多个分支指定合并其中一部分内容
# 首先在github/gitlab等新建repo
git init /tmp/testproject; cd /tmp/testproject;

# 在 main 分支下准备提交记录
git checkout main

echo aa >>  aa.txt;
git add .; git commit -m "add aa.txt"

echo bb >> bb.txt;
git add .; git commit -m "add bb.txt"

echo cc >> cc.txt;
git add .; git commit -m "add cc.txt"

#git push origin main # 若想完整测试则应推送

# 在切到 dev 分支准备新功能的提交记录
git checkout -b dev

echo dd >> dd.txt;
git add .; git commit -m "add dd.txt"

echo ee >> ee.txt;
git add .; git commit -m "add ee.txt"

#git push origin dev # 若想完整测试则应推送

# 这时应需求方想尽快发布(假设发布分支为 main), dd 特性是本次要发布的目标, 但 ee 特性有BUG不能发布, 怎么办?
git checkout main # 先切回 main 分支

# 先找到 dd 提交对应的 commit id
export tmp_commitid=$(git log --grep="dd.txt" --pretty=format:"%H")

# 将指定的 commitId 增量式合并到当前 main 分支, 这会在当前分支产生一个新的提交, 当然哈希值就会跟原来的不一样
git cherry-pick $tmp_commitid

# 查看log(除可能有的Init Commit外会有4条记录, 分别是: aa,bb,cc,dd, 没有 ee)
git log

# 清理现场
\rm -rf /tmp/testproject
  • 示意图
main branch:   aa -> bb  ->  cc  ->  dd(需求方想要发布的目标commit)
                         \   /
 dev branch:               dd  ->  ee(存在BUG不能发布)

2. 使用 git commit --amend 修正提交记录的日期

  • 2.1 常用于某一分支补充漏提交
# 准备示例(模拟两个用户)
mkdir -p /tmp/{user1,user2}

# --- 模拟 user1 操作(首先在github/gitlab等新建repo) ---
cd /tmp/user1
git init testproject; cd testproject;

echo aa >> aa.txt;
git add .; git commit -m "add aa.txt"

echo bb >> bb.txt;
git add .; git commit -m "add bb.txt"

echo cc >> cc.txt;
git add .

## 覆盖最后一次提交的日期(亲测发现 gitee 只需 --date 即可识别,但 gitlab 必须使用环境变量 GIT_COMMITTER_DATE 才能生效,因此为了兼容都写上吧)
export GIT_COMMITTER_DATE="Fri Jun 11 11:46:22 2021 +0800"
git commit --amend --no-edit --date "$GIT_COMMITTER_DATE"

## 同理, 覆盖最后一次提交的作者和注释信息
#export GIT_COMMITTER_NAME="jacks01 <jacks01@gmail.com>"
#git commit --amend --no-edit --author "$GIT_COMMITTER_NAME" -m "Newly description"
git push -f # 必须强推?

# 再查看 log 会看到最后提交的时间、注释、作者都已被覆盖
git log

# --- 模拟 user2 操作 ---

cd /tmp/user2
#git clone git@gitxx.com/xxx/testproject
cd testproject

# 查看log, 与 user1 看到的一致
git log

# 清理现场
\rm -rf /tmp/{user1,user2}
# 修改最近三次注释信息(本质就是rebase最近几次commit)
git rebase -i HEAD~3

3. 已 push 的记录如何合并?

# 合并前三个commit
git rebase -i HEAD~3
# 或找到倒数第三个commit id
git rebase -i a027673196c2101e512893641b92c60cb60c3920
# 重新(强制)推送
git push -f

4. 使用 git verify-pack 解决 .git目录过大问题

  • 原因分析:.git 目录主要用来记录每次提交的变动,当我们的项目越来越大的时就会越来越大。
    很大的可能是因为提交了大文件,如果你提交了大文件 A,那么即使你在之后的版本中将其删除,但实际上,记录中的大文件仍然存在。原因在于虽然你在后面的版本中删除了大文件A,但是Git是有版本倒退功能,那么如果大文件A不记录下来,git拿什么来回退呢?
    git 给出了解决方案,使用git branch-filter来遍历 git history tree, 可以永久删除history中的大文件,达到让.git文件瘦身的目的。
# 1. 找出大文件的前5个
git verify-pack -v .git/objects/pack/pack-*.idx | sort -k 3 -g | tail -5

# 2. 找出大文件的文件名
git rev-list --objects --all | grep 8f10eff91bb6aa2de1f5d096ee2e1687b0eab007

# 3. 清除该文件的所有历史记录并强制刷新到所有分支(慎重,需要管理员权限,否则报错)
git filter-branch --index-filter 'git rm --cached --ignore-unmatch <your-file-name>'
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git fsck --full --unreachable
git repack -A -d
git gc --aggressive --prune=now
git push --force [remote] master

参考

留言

您的电子邮箱地址不会被公开。