1. 程式人生 > >Git自動化合並多個Commit

Git自動化合並多個Commit

當我 path def uri cal 目錄 trunc res local

目錄

  • git rebase邏輯
  • git editor的修改
  • 處理git-rebase-todo文件
  • Python實現

當我們有多個commit或者從開源處拿到多個commit時,想合成一個commit,並保留每個commit的message時,大家都知道用"git rebase -i"可以解決,但這種方式需要手動進行操作,假如我們要處理的比較多,就想要自動化來處理,下面介紹下怎麽自動化處理。

git rebase邏輯

當我們"git rebase -i"後,git在當前.git/rebase-merge目錄下生成git-rebase-todo文件,然後調用git editor來讓用戶編輯git-rebase-todo文件進行處理,如果實現自動化就需要:

  1. 修改git editor來使用我們提供的;
  2. 腳本來處理進行git-rebase-todo文件的處理。

git editor的修改

git提供config命令來查看配置和修改配置,同樣editor也可以這樣進行設置。

    git config core.editor #查看當前使用editor
    git config --local --replace-all  core.editor NEW_EDITOR # 修改當前的倉庫的editor為NEW_EDITOR

處理git-rebase-todo文件

pick 62e0071 first commit
pick 3bd641a second commit
pick 92c03c7 third commit

# 變基 7073047..92c03c7 到 7073047(3 個提交)
#
# 命令:
# p, pick <提交> = 使用提交
# r, reword <提交> = 使用提交,但修改提交說明
# e, edit <提交> = 使用提交,進入 shell 以便進行提交修補
# s, squash <提交> = 使用提交,但融合到前一個提交
# f, fixup <提交> = 類似於 "squash",但丟棄提交說明日誌
# x, exec <命令> = 使用 shell 運行命令(此行剩余部分)
# b, break = 在此處停止(使用 'git rebase --continue' 繼續變基)
# d, drop <提交> = 刪除提交
# l, label <label> = 為當前 HEAD 打上標記
# t, reset <label> = 重置 HEAD 到該標記
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       創建一個合並提交,並使用原始的合並提交說明(如果沒有指定
# .       原始提交,使用註釋部分的 oneline 作為提交說明)。使用
# .       -c <提交> 可以編輯提交說明。
#
# 可以對這些行重新排序,將從上至下執行。
#
# 如果您在這裏刪除一行,對應的提交將會丟失。
#
# 然而,如果您刪除全部內容,變基操作將會終止。
#
# 註意空提交已被註釋掉

上面是有3個commit,需要將後面2個commit合並到第1個,通過後面的註釋可以看到,squash是將commit合並到前一個commit上,所以需要將後2個的pick修改為squash,即修改為下面這樣:

pick 62e0071 first commit
squash 3bd641a second commit
squash 92c03c7 third commit

Python實現

使用python實現上述邏輯

#!/usr/bin/env python3
#encoding: UTF-8

import os
import sys

def change_editor(current_file):
    os.system("git config --local --replace-all  core.editor " + current_file) # 將當前腳本設置為editor
    os.system("git rebase -i") # 執行rebase,觸發調用該腳本進行rebase
    os.system("git config --local --replace-all core.editor vim") # 執行完後將editor設置回vim

def rebase_commits(todo_file):
    with open(todo_file, "r+") as f:
        contents = f.read() # 讀取git-rebase-todo文件內容
        contents = contents.split("\n")
        first_commit = True
        f.truncate()
        f.seek(0)
        for content in contents:
            if content.startswith("pick"):
                if first_commit:
                    first_commit = False
                else:
                    content = content.replace("pick", "squash") # 將除了第一個pick修改為squash
            f.write(content + "\n")

def main(args):
    if len(args) == 2:  # 如果將該腳本作為editor,git會調用該腳本,並以git-rebase-todo文件作為第2個參數
        rebase_commits(args[1])
    else:
        change_editor(os.path.abspath(args[0])) # 設置git editor

if __name__ == "__main__":
    main(sys.argv)

URL: https://liwugang.github.io/2019/04/28/git_commits/

Git自動化合並多個Commit