如何最好地压缩旧的提交记录

21

最近有一位开发人员离开了,他在几个月前的一个仓库中留下了大量只包含“更新”字样的提交记录。理想情况下,我想将它们压缩成一个单独的提交记录,但我只对最近的提交记录这样做过。

如果像下面这样的提交记录很多(假设是两个月前的),我该如何处理?

.... 从两个月前开始

aabbcc updated
aabbdd updated
aabbee updated
aabbff updated

我并不需要什么复杂的东西,只是一个简单的解决方案。这些提交(除了今天与我分享)还没有被公开共享,因此不会影响其他人的提交历史。

3个回答

10
为了执行 git squash,请按照以下步骤进行操作:
// X is the number of commits you wish to squash
git rebase -i HEAD~X

一旦您压缩提交记录 - 选择s以进行压缩 = 它将把所有提交记录合并成一个提交记录。

enter image description here


如果需要,您还可以使用--root标志
尝试:git rebase -i --root --root
Rebase all commits reachable from <branch>, instead of limiting them with
an <upstream>.

This allows you to rebase the root commit(s) on a branch.  
When used with --onto, it will skip changes already contained in `<newbase>`   
(instead of `<upstream>`) whereas without --onto it will operate on every 
change. When used together with both --onto and --preserve-merges, all root 
commits will be rewritten to have `<newbase>` as parent instead.`

1
我还没有尝试过,是否有办法向rebase -i传递一系列的提交ID,例如aabbcc..aabbbff? - timpone
@timpone 不是交互式变基,而是一个使用“git cherry-pick”脚本的工具。通过“cherry-pick”,您可以选择要操作的代码范围。 - Kaz
1
射击 - 一个愚蠢的问题,但是否有可能在特定点检出,然后执行类似于 git rebase -i HEAD~200 的操作?还是让它保持原样更安全,我完全可以接受。 - timpone
阅读此内容(如果您喜欢,也可以随意投票支持它) https://dev59.com/ulsW5IYBdhLWcg3w2qNM#34519716 - CodeWizard
1
好的,请告诉我如果您需要关于这个问题的更多帮助 :-) - CodeWizard
显示剩余5条评论

5

我知道这已经是一个古老的问题,但我需要一个解决方案。

简而言之,我的本地git仓库(在NFS上,没有上游)作为某些文件的备份,并希望最多有50个提交。由于有许多文件并且备份相当频繁,我需要自动压缩历史记录的工具,因此我创建了一个同时进行文件备份和压缩历史记录的脚本。

#!/bin/bash

# Max number of commits preserved
MAX_COMMITS=50

# First commit (HEAD~<number>) to be squashed
FIRST_SQUASH=$(echo "${MAX_COMMITS}-1"|bc)

# Number of commits until squash
SQUASH_LIMIT=60

# Date and time for commit message
DATE=$(date +'%F %R')

# Number of current commits
CURRENT_COMMITS=$(git log --oneline|wc -l)

if [ "${CURRENT_COMMITS}" -gt "${SQUASH_LIMIT}" ]; then

    # Checkout a new branch 'temp' with the first commit to be squashed
    git checkout -b temp HEAD~${FIRST_SQUASH}

    # Reset (soft) to the very first commit in history
    git reset $(git rev-list --max-parents=0 --abbrev-commit HEAD)

    # Add and commit (--amend) all the files
    git add -A
    git commit --amend -m "Automatic squash on ${DATE}"

    # Cherry pick all the non-squashed commits from 'master'
    git cherry-pick master~${FIRST_SQUASH}..master

    # Delete the 'master' branch and rename the 'temp' to 'master'
    git branch -D master
    git branch -m master

fi

所以,这个脚本的基本功能是(我去掉了备份部分):
  1. 如果有超过60个提交,它会将50到60+的所有提交压缩成一个提交。
  2. 创建并检出一个基于提交的新分支
  3. 将剩余的提交从主分支(#1到#49)挑选到该分支上
  4. 删除主分支
  5. 将新分支重命名为主分支。

这种方法对于跟踪二进制文件来说是一个不错的选择,但是使用这种方法后.git文件夹的大小会增加一倍。我在尝试这个链接中的方法 https://dev59.com/KG865IYBdhLWcg3wd-ce ,但是无法显著减小.git文件夹的大小。这是因为它使用了cherry pick和删除分支而不是压缩吗? - izzulmakin
1
它变得更大是因为使用了 git add -A,而我手动将 .git 复制到 .gitbk 中,这个文件夹显然不在 .gitignore 中,所以也被添加了进来!在我的情况下,我将那一行编辑成了 git add \git ls-tree --full-tree -r --name-only HEAD`并添加了git gc --aggressive`。 - izzulmakin
2
bc isn't always present. You can use built-in bash arithmetic to add a bit more portability: FIRST_SQUASH=$(expr $MAX_COMMITS - 1) - EdwardTeach

4
提交的年龄并不重要,合并提交就是合并提交。
如果您不喜欢变基,或者有成千上万个提交需要合并,您可以轻松地将其重置到第一个提交哈希值,并重新提交所有内容:
$ git reset aabbff 
$ git commit -m "This commit now contains everything from the tip until aabbff"

你只需要一个提交,就像变基->合并一样。

哈哈,不是成千上万,只有大约200个,而且它们都来自于他刚开始提交的那段时间。有没有一种方法可以将其重置从aabbff到另一个特定的提交(就像波浪符号的反向操作一样)。抱歉,我绝对不是git大师,所以我最担心的就是搞砸了什么东西。 - timpone
嘿@timpone - 不,reset命令将从分支的末尾重置到您指定的修订/哈希。如果您想针对分支历史记录中间的一系列提交进行操作,则应该使用rebase。 - scrowler
仅为添加额外说明,提交哈希应该是要压缩更改的提交之前的一个提交的哈希。 - Aleks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接