我使用此脚本修改提交:
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 ../
它从第一个回购中提取数据,修改提交者信息并推送到第二个回购。
如果有人直接提交第二个回购,问题就出现了。如何将这些更改应用于第一个回购?
答案 0 :(得分:6)
如果我正确理解您的问题(阅读评论后),您的回购目前看起来像这样:
第一个回购(广告)中的提交已被修改以创建备用提交(a' -d'),这些提交被推入第二个回购,然后添加了其他提交,(例如)。 / p>
因为您在两个回购邮件中的身份信息之间没有1:1的关系,因此尝试修改' -d'使用filter-branch以恢复原始历史记录,而理论上可能,将需要一种能够肯定地识别原始提交的方法'没有确定提交(其哈希)所需的一条信息。
提交基本上由几条信息组成:
所有这些都经过哈希处理,以便为您的提交创建唯一标识符。改变了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
此命令将输出提交指向的树对象,如果两个树匹配,则您将处理相同的代码。完全可能在没有匹配代码库的情况下执行以下过程,但您可能必须解决该情况下的冲突。这一步真的只是告诉你两者将如何轻松融合在一起。
如果您最初修改提交的repo完好无损,则可以将两者中的分支提取到一个repo中,并尝试使用cherry-pick复制提交。
git checkout <branch at d>
git cherry-pick d'...g
(注意语法是3个点)这将在(但不包括)d&#39;之后应用每次提交的更改。直到并包括g到d。创建新提交e&#39; -g&#39;。
如果您没有简单的方法将更改从两个分支转换为单个仓库,您可以为第二个仓库中的提交创建一系列补丁并将其应用到第一个仓库。
git checkout <branch of g>
git format-patch --output-directory <dir> d'...g
(同样,语法是3个点)这将在(并且不包括)d&#39;之后输出每个提交的一系列补丁文件。直至并包括g。然后将这些文件复制到第一个存储库中可以获取这些文件的位置。
git checkout <branch of d>
git am /path/to/patches/*
你最终会在樱桃采摘方法的同一个地方结束。
如果存在很多冲突并且您不需要保留身份更改信息,您也可以使用git replace
执行移植。
git replace --graft e d
这将创建一个提交e的副本,其中d作为父项,并添加一个表示使用e&#39;每当它试图访问e时提交。有效地使d成为两者的共同祖先,并允许您执行传统的合并(h)。
在没有共同历史记录的同时保留两个repos将始终导致这样的问题,并且随着两者缓慢分歧(例如,当你解决冲突时)它们会变得更糟。随着时间的推移,这两种方法都需要越来越多的资源来维护这两个回购。
我建议一旦两个repos同步,选择其中一个并从那时起专门使用那个。如果您需要两个遥控器,只需将该回购推送给它们。然后,您可以轻松地使用许多经过验证的真实工作流程来维护两个回购。
如果这不是一个选项,我建议一丝不苟地检查两个回购头的树木,以验证它们是否经常一点一点地相同。
答案 1 :(得分:0)