Git squash sequence fixed by author to compress history

My team worked on a long functional branch, which now has hundreds of commits, and now I need to combine it into a master version for release.

I don’t want to have as many commits in this thread, since many commits were made to fix errors and only change a couple of lines to a commit.

On the PR creation page in Github, it restricts the commits shown at 250.

From Github - "This comparison is great! Only showed the last 250 commits"

Therefore, I decided to compress the story in such a way that a set of consecutive commits from the author falls into a single commit.

Let's say we have such commits as: A - A - A - B - B - A - C - D - D - B- B -Afrom the authors A, B, C and D, then the resulting commit log will have A (3) - B(2) - A - C - D (2) - B(2) - A where X` (N) is a compressed commit N commits from author X.

Edit: I understand that this will need a script, and I'm looking for the same thing. I do not want to go through an interactive reboot to do the same.

+4
source share
2 answers

Console:

git log --format="p|%h|%an|%s" --no-merges -n 190 | tail -r  > commits.txt

PHP:

$fp = fopen("./commits.txt", "r");

$commits = array();
$previous_author = '';
while (($line = fgets($fp)) !== FALSE) {
  list($mode, $sha, $current_author, $subject) = explode('|', $line);
  if ($previous_author == '' || $previous_author !== $current_author) {
    $previous_author = $current_author;
  }
  else {
    $mode = 'f';
  }
  $output[] = implode(' ', array($mode, $sha, $subject));
}

fclose($fp);

print implode(' ', $output);

Console:

git rebase -i HEAD~190

In the interactive editor, they deleted everything and inserted the php script output above. I could achieve the intended results.

0
source

Nothing has been created for this; you will have to write your own script.

, git rev-list git log ( , ), , . , -- . , , feature target, :

git rev-list --reverse --topo-order target..feature > /tmp/list

SHA-1 . , , :

while read sha1; do
    author_name=$(git log -n 1 --format=%an $sha1)
    ...
done < /tmp/list

, , , . $author_name , , , ( ), , . , ... . , target. .

, : - , git commit-tree, .

, :

# add new squash-style commit using commit $1
make_squash_commit() {
    local sha1=$1 tree new_sha1

    tree=$(git rev-parse $sha1^{tree})
    new_sha1=$(git commit-tree $tree -p HEAD)
    git update-ref -m "squash $sha1" HEAD $new_sha1
}

set -e
git rev-list --reverse --topo-order target..feature > /tmp/list
git checkout --detach target
: > /tmp/accum_log
prev_sha1=""
while read sha1; do
    author_name=$(git log -n 1 --format=%an $sha1)
    if [ "$author_name" != "$prev_name" -a -n "$prev_sha1" ]; then
        make_squash_commit $prev_sha1 < /tmp/accum_log
        : > /tmp/accum_log
    fi
    prev_name="$author_name"
    prev_sha1=$sha1
    git log -n 1 --format="%B" $sha1 >> /tmp/accum_log
done < /tmp/list
if [ -z "$prev_sha1" ]; then
    echo "Warning: no commits found to squash!"
    sha1=$(git rev-parse target)
fi
# squash final commit, then give anonymous branch a name
make_squash_commit $prev_sha1 < /tmp/accum_log
git checkout -b temp_branch
rm /tmp/list /tmp/accum_log

script : , ( , , , ). "" , git commit-tree (. ).

+1

Source: https://habr.com/ru/post/1618850/


All Articles