基於Git rebase修改歷史提交資訊

LuZ發表於2019-05-07

說明

關於為什麼要修改歷史提交的作者資訊和提交資訊,我就不多說了,也許是專案規範要求,也許是自己強迫症,總之是有這樣的需求。

開始之前先說明一下:

  • 本文介紹的方法只適用於本地倉庫,提交到遠端以後,我沒測試過,也不太清楚。
  • 本文介紹的方法基於rebase實現,適用於修改任意歷史提交,不限於最近一條。

開始之前我們需要一個git程式碼庫作為實驗物件,該程式碼庫的概況如下,輸入如下命令檢視:

git log --graph --pretty='%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an %ae>%Creset'
複製程式碼

輸出如下:

* e5f026b - (HEAD -> dev) 新增解析度獲取 (17 hours ago) <foo foo@foo.com>
* 51c6763 - 獲取core number、device model、ram、diskspace (17 hours ago) <foo foo@foo.com>
* 7075919 - Add commnet (17 hours ago) <foo foo@foo.com>
* 06c4637 - Get SSID and BSSID (17 hours ago) <foo foo@foo.com>
* 4406428 - Get DNS (17 hours ago) <foo foo@foo.com>
* 28169b0 - Get router IP (17 hours ago) <foo foo@foo.com>
* db9b32c - Rename: Device+Info -> Device+Networking (17 hours ago) <foo foo@foo.com>
* 53d87f9 - Get WiFi and Celluar IP Address (17 hours ago) <foo foo@foo.com>
複製程式碼

下文中的操作都是基於該程式碼庫實現。

修改歷史提交的作者資訊

界定修改範圍

在修改之前,首先需要明確自己的修改範圍,rebase操作執行時,允許我們指定rebase範圍,比如要修改最近兩條提交的作者資訊,輸入如下命令:

git reabse -i 7075919
複製程式碼

該命令中-i參數列明我們需要以互動式的方式來執行rebase操作。7075919為rebase操作的起始點,表示對(7075919, HEAD]之間的提交進行rebase,注意不包含7075919這條提交本身。

那麼問題來了,如何對所有的提交進行rebase呢?單純地輸入:

git reabse -i 53d87f9
複製程式碼

是不行的,因為該命令不會將提交53d87f9納入rebase。

如果要從第一條提交開始rebase,輸入如下命令即可:

git rebase -i --root
複製程式碼

該命令會將所有提交納入rebase。

選擇要更改的提交

執行git reabse -i 7075919命令後,git預設的編輯器會開啟,顯示內容如下:

pick 51c6763 獲取core number、device model、ram、diskspace
pick e5f026b 新增解析度獲取

# Rebase 7075919..e5f026b onto 7075919 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
複製程式碼

可以看到,待修改的提交前面都有一個命令,預設是pick,表示rebae過中直接使用該提交,不做修改,提交列表下面的註釋說明中還列舉了其他命令,感興趣的話大家可以去看下,此處便不贅述了。

此處我們要修改提交e5f026b的作者資訊,直接編輯該提交前面的命令,將pick改成edit,也可以簡寫為e,效果一樣的,編輯的後的內容如下,此處我省略了註釋文案:

pick 51c6763 獲取core number、device model、ram、diskspace
edit e5f026b 新增解析度獲取

# ...
複製程式碼

然後儲存修改,並關閉編輯重啟,我用的是vim,直接:wq退出,控制檯會輸出如下內容:

➜  Test git:(dev) git rebase -i 7075919
Stopped at e5f026b...  新增解析度獲取
You can amend the commit now, with

  git commit --amend

Once you are satisfied with your changes, run

  git rebase --continue
➜  Test git:(e5f026b)
複製程式碼

這表明git當前處於互動式rebase過程中,初始時指向第一條需要修改的提交。控制檯輸出表明當前正在對提交e5f026b進行rebase,這正是我們需要修改的第一條提交。

更改作者資訊

輸入如下命令,修改作者資訊:

git commit --amend --author="bar <bar@bar.com>" --no-edit && git rebase --continue
複製程式碼

此處我們只有一條提交需要rebase,上述命令執行結束後,控制檯輸出如下:

➜  Test git:(e5f026b) git commit --amend --author="bar <bar@bar.com>" --no-edit && git rebase --continue
[detached HEAD fa3caab] 新增解析度獲取
 Author: bar <bar@bar.com>
 Date: Mon Apr 29 10:49:08 2019 +0800
 3 files changed, 28 insertions(+)
Successfully rebased and updated refs/heads/dev.
➜  Test git:(dev)
複製程式碼

表明rebase結束,修改已生效,當前提交的HEAD指標已指向了dev。此處由於我們只有一條提交需要修改,所以該提交的修改結束也意味著整個rebase過程的結束,如果有多條提交需要修改,每完成一條提交的rebase以後,rebase便會停下來,並進入下一條提交的處理。

此時檢視修改後的程式碼庫狀態如下:

* fa3caab - (HEAD -> dev) 新增解析度獲取 (12 minutes ago) <bar bar@bar.com>
* 51c6763 - 獲取core number、device model、ram、diskspace (17 hours ago) <foo foo@foo.com>
* 7075919 - Add commnet (17 hours ago) <foo foo@foo.com>
* 06c4637 - Get SSID and BSSID (17 hours ago) <foo foo@foo.com>
* 4406428 - Get DNS (17 hours ago) <foo foo@foo.com>
* 28169b0 - Get router IP (17 hours ago) <foo foo@foo.com>
* db9b32c - Rename: Device+Info -> Device+Networking (17 hours ago) <foo foo@foo.com>
* 53d87f9 - Get WiFi and Celluar IP Address (17 hours ago) <foo foo@foo.com>
複製程式碼

可以發現,提交的作者資訊已經成功修改,並且生成了新的SHA-1。

修改歷史提交的提交資訊

修改歷史提交資訊與修改作者資訊類似,同樣基於rebase實現。此處仍以修改最近兩條提交的提交資訊為例,闡明修改過程。

執行git reabse -i 7075919命令界定修改範圍以後,在編輯器內選擇要修改的提交,此處我們選擇修改提交51c6763的提交資訊,將pick改成reword,如下所示:

reword 51c6763 獲取core number、device model、ram、diskspace
pick fa3caab 新增解析度獲取

# ...
複製程式碼

儲存並退出編輯器。

更改提交資訊

上一步退出編輯器後,rebase開始執行,此時會再次開啟預設的編輯器,顯示如下:

獲取core number、device model、ram、diskspace

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Author:    foo <foo@foo.com>
# Date:      Wed Apr 24 15:32:49 2019 +0800
#
# interactive rebase in progress; onto 7075919
# Last command done (1 command done):
#    reword 51c6763 獲取core number、device model、ram、diskspace
# Next command to do (1 remaining command):
#    pick fa3caab 新增解析度獲取
# You are currently editing a commit while rebasing branch 'dev' on '7075919'.
#
# Changes to be committed:
#	modified:   DeviceInfo.xcodeproj/project.pbxproj
#	new file:   DeviceInfo/UIDevice+Hardware.h
#	new file:   DeviceInfo/UIDevice+Hardware.m
#	modified:   DeviceInfo/ViewController.m
#
複製程式碼

直接編輯提交資訊進行修改即可,此處我們將提交資訊修改為:

修改歷史提交資訊:獲取core number、device model、ram、diskspace

# ...
複製程式碼

修改完成後儲存退出,即完成了對歷史提交的修改,控制檯輸出如下:

➜  Test git:(dev) git rebase -i 7075919
[detached HEAD ac74c92] 修改歷史資訊:獲取core number、device model、ram、diskspace
 Author: foo <foo@foo.com>
 Date: Wed Apr 24 15:32:49 2019 +0800
 4 files changed, 79 insertions(+), 1 deletion(-)
 create mode 100644 DeviceInfo/UIDevice+Hardware.h
 create mode 100644 DeviceInfo/UIDevice+Hardware.m
Successfully rebased and updated refs/heads/dev.
➜  Test git:(dev)
複製程式碼

表明修改成功。

此時檢視修改後的程式碼庫狀態如下:

* d5cedac - (HEAD -> dev) 新增解析度獲取 (71 seconds ago) <bar bar@bar.com>
* ac74c92 - 修改歷史資訊:獲取core number、device model、ram、diskspace (8 minutes ago) <foo foo@foo.com>
* 7075919 - Add commnet (20 hours ago) <foo foo@foo.com>
* 06c4637 - Get SSID and BSSID (20 hours ago) <foo foo@foo.com>
* 4406428 - Get DNS (20 hours ago) <foo foo@foo.com>
* 28169b0 - Get router IP (20 hours ago) <foo foo@foo.com>
* db9b32c - Rename: Device+Info -> Device+Networking (20 hours ago) <foo foo@foo.com>
* 53d87f9 - Get WiFi and Celluar IP Address (20 hours ago) <foo foo@foo.com>
複製程式碼

可以發現,歷史提交的提交資訊已經成功修改,並且生成了新的SHA-1。

總結

本文基於rebase,闡明瞭如何修改歷史提交的的作者資訊和提交資訊。其實從執行過程中可以看到,rebase的功能並不止於此,我們只用到了edit、pick、reword三種命令,除此之外,rebase還支援fixup、exec、drop能命令,可供完成更復雜的需求。

參考

www.git-tower.com/learn/git/f…

相關文章