簡體   English   中英

Git:更改提交者信息

[英]Git: changing committers info

我正在使用此腳本來修改提交:

rm -rf repo

echo "clonning $1"
git clone $1 repo

cd repo
git checkout dev

echo "setting remote origin to $2"
git remote set-url origin $2

array=( 'email1@gmail.com' 'email2@gmail.com' )
for OLD_EMAIL in "${array[@]}"
do
  echo $OLD_EMAIL
  git filter-branch -f --env-filter '
  CORRECT_NAME="New name"
  CORRECT_EMAIL="new@email.com"
  if [ "$GIT_COMMITTER_EMAIL" = '$OLD_EMAIL' ]
  then
      export GIT_COMMITTER_NAME="$CORRECT_NAME"
      export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
  fi
  if [ "$GIT_AUTHOR_EMAIL" = '$OLD_EMAIL' ]
  then
      export GIT_AUTHOR_NAME="$CORRECT_NAME"
      export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
  fi
  ' --tag-name-filter cat -- --tags
done
echo "Authors list:"
git log --format='%cE' | sort -u
echo -n "Push to destination (y/n)? "
read answer
if echo "$answer" | grep -iq "^y" ;then
    git push
else
    echo Aborted
fi

cd ../

它從第一個倉庫中提取數據,修改提交者信息並推送到第二個倉庫。

如果有人直接提交第二個回購,問題就出現了。 如何將這些更改應用於第一個回購?

如果我正確理解你的問題(閱讀評論后),你的回購目前看起來像這樣:

初始狀態

第一個repo(ad)中的提交已被修改以創建備用提交(a'-d'),這些提交被推入第二個倉庫,然后添加了其他提交(例如)。

重新編輯您的歷史記錄

因為你在兩個repos中的身份信息之間沒有1:1的關系,試圖修改帶有filter-branch的'-d'以恢復原始歷史,雖然理論上可行,但是需要一個積極的方法識別“原始提交”,而沒有確定提交(其哈希)所需的一條信息。

提交基本上由幾條信息組成:

  1. 樹的哈希
  2. 提交的父級的哈希值
  3. 作者的身份信息
  4. 創作的時間戳
  5. 提交者的身份信息
  6. 提交的時間戳
  7. 提交消息
  8. 所有信息的大小

所有這些都經過哈希處理,以便為您的提交創建唯一標識符。 改變了2,3,5和8之后,我們留下了樹,它不一定是唯一的,時間戳(不一定是唯一的)和提交消息,它不一定是唯一的。

可能只是比較樹和其中一個時間戳,你可以獲得一個不錯的匹配,所以讓我們為該場景編寫一些偽代碼。

# create a variable to hold the information from teh current commit
pseudoidentifier=$TREE + $AUTHOR_TIMESTAMP

# go to the first repo
cd /path/to/firstrepo

# output the log | grep to search | sed to remove everything after delimeter
oldhash=`git log --format="{hash}~{tree}{authortimestamp}" | grep pseudoidenfier | sed "s/~.+$//"`

# get the new identity using a custom formatted show command
newidentity=`git show -q --format="{formatted identity}" $oldhash`

# parse out the name and email, probably with sed
CORRECT_NAME=`sed 's/pattern//' $newidentity`
CORRECT_EMAIL=`sed 's/pattern//' $newidentity`

# go to the second repo
cd /path/to/secondrepo

export GIT_COMMITTER_NAME="$CORRECT_NAME"
export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"

不幸的是,編寫速度慢,測試困難且耗時。 可能需要多次重新運行整個事物。 因為你的最終目標是重新統一代碼。 還有其他一些選項可能會減少頭痛並且速度更快。 特別是如果你確實需要保持第二個回復,身份更新完好無損。

替代方法

如果沒有共同的歷史記錄,您仍然可以使用更多手動方式將兩者同步。 在這種情況下,我建議使用以下三種方法。

一點前期工作

在開始之前,我們可以檢查d和d'處的代碼是否確實相同。 我們可以使用git show命令來做到這一點:

$ git show -q --format="%T" d
a017285da45ec06fc744815f33a2e22627f4a799
$ git show -q --format="%T" d'
a017285da45ec06fc744815f33a2e22627f4a799

此命令將輸出提交指向的樹對象,如果兩個樹匹配,則表示您正在處理相同的代碼。 完全可能在沒有匹配的代碼庫的情況下執行以下過程,但在這種情況下您可能必須解決沖突。 這一步真的只是告訴你兩者將如何輕松地融合在一起。

Cherry-Pick方法

如果您最初修改提交的repo完好無損,則可以從兩者中獲取分支到單個repo中,並嘗試使用cherry-pick復制提交。

git checkout <branch at d>
git cherry-pick d'...g

(注意語法是3個點)這將在d'之后(但不包括)d'應用每個提交的更改,直到並包括g到d。 創建新提交e'-g'。

櫻桃采摘后的歷史

補丁方法

如果您沒有簡單的方法將更改從兩個分支轉換為單個存儲庫,則可以為第二個存儲庫上的提交創建一系列修補程序並將其應用於第一個存儲庫。

在第二個回購

git checkout <branch of g>
git format-patch --output-directory <dir> d'...g

(再次,語法是3個點)這將在d'之后(並且不包括)d'之前和之后為每個提交輸出一系列補丁文件。 然后將這些文件復制到第一個存儲庫中可以獲取這些文件的位置。

在第一個回購

git checkout <branch of d>
git am /path/to/patches/*

你最終會在櫻桃采摘方法的同一個地方。

補丁后的歷史

創建一個移植

如果存在大量沖突並且您不需要保留身份更改信息,則還可以使用git replace來執行移植。

git replace --graft e d

這將創建一個commit e的副本,其中d作為父項,並添加一個引用,表示在嘗試訪問e時使用e'commit。 有效地使d成為兩者的共同祖先並允許您執行傳統合並(h)。

在此輸入圖像描述

那又怎樣?

保持兩個沒有共同歷史記錄同步的回購將一直導致你這樣的問題,並且隨着兩者的緩慢分歧(例如,當你解決沖突時)它們會變得更糟。 隨着時間的推移,這兩種方法都需要越來越多的資源來維護兩個回購。

我建議,一旦兩個repos同步,選擇其中一個並從那時起專門使用那個。 如果您需要兩個遙控器,只需將該回購推送給它們。 然后,您可以輕松地使用許多經過驗證的真實工作流程中的任何一個來維護兩個回購。

如果這不是一個選項,我建議一絲不苟地檢查兩個回購頭的樹木,以驗證它們是否經常相同。

你有兩個選擇來完成這個任務:

  1. 如果你信任用戶,你可以讓他們更改他們的電子郵件(只有這個git repo或所有repos,為所有repos添加--global
 git config user.email email@server.com 
  1. 如果你想通過預提交git鈎子強制執行它,那么你將添加到第二個存儲庫並讓它們全部拉出新的更新。 有關這方面的更多信息,請點擊 此處此處

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM