我有一个包含两个主要分支的 Git 存储库:master 和 dev。目前看起来像这样:
master ( )----( )----(A)----(B)----(C)
\
\
dev ( )----( )----( )----( )----(~ 30 additional commits...)
非常简单,除了 master 上的提交 A 包含对文件和文件夹结构的重大更改(基本上,我使用 the steps shown here 将存储库在层次结构中向上移动一级)。
我想继续在 dev 分支上工作,但是当我试图将 dev rebase 到 master 以将新文件结构引入 dev 时,Git 出现了大量错误。我用 git reset
恢复了正常状态,但根据我(有点有限)的 Git 经验,许多错误通常意味着我采用了错误的方法。
是否有更好的方法将重组后的文件夹结构移交给 dev 分支?如果有帮助,master 上的其他提交(B 和 C)的更改非常小,如果可以让事情变得更容易,我可以接受丢失它们。
最佳答案
是的,有一种明智的方法可以做到这一点。
前言
master
现在是(如果我理解正确的话):
project
src
file.c
dev
是,因为它不包含提交 A
:
src
file.c # with some changes
你的分支是这样的:
master ( )----(A0)----(A)----(B)----(C)
\
\
dev (D1)----(D2)----(D3)----( )----(~ 30 additional commits...)
我还假设 A
与 A0
没有任何区别,除了 project/
被插入到所有文件路径中(“移动你的tree up"进入新的 project
根目录,根据您的链接问题)。
让我们开始吧...
我们做的正是 git rebase
在内部做的事情,同时在每个步骤上通过做我们自己的“cherry-pick”步骤而不是什么来愚弄 git
git
会自己做。
我们使用第二个工作目录。 $WD1
是原始工作目录的绝对路径,$WD2
是其他绝对路径(在该目录之外)。
首先,创建您的帮助目录作为原始目录的克隆:
cd $WD2
git clone $WD1 dev .
然后,开始一个分支newdev
,它最终会在A
的基础上被dev
rebased。
cd $WD1
git checkout A
git checkout -b newdev
我们将 D1
提交到 newdev
中,而不给 git
任何搞砸它的机会:
cd $WD2
git checkout D1
cd $WD1
rm -r project/src
cp -r $WD2/src project/
git add -A
git commit -m "`cd $WD2 ; git log -1 --format=%s`"
现在的情况是:
newdev (D1')
/
/
master ( )----(A0)----(A)----(B)----(C)
\
\
dev (D1)----(D2)----(D3)----( )----(~ 30 additional commits...)
现在,为 D2
重复:
cd $WD2
git checkout D2
cd $WD1
rm -r project/src
cp -r $WD2/src project/
git add -A
git commit -m "`cd $WD2 ; git log -1 --format=%s`"
现在的情况是:
newdev (D1')----(D2')
/
/
master ( )----(A0)----(A)----(B)----(C)
\
\
dev (D1)----(D2)----(D3)----( )----(~ 30 additional commits...)
重复直到完成。
当然,您会希望为这些命令创建一个小的 shell 脚本,它会遍历所有提交 D1 ... D30
。
之后,一个简单的 git rebase master
将照常从 A
rebase 到 C
。然后,通过更改周围的名称来摆脱 newdev
:
git checkout newdev
git branch olddev dev # just in case...
git branch -D dev
git checkout -b dev
一般注意事项
为什么是第二个工作目录?
请注意,在这种特殊情况下,可能有一些方法可以避免使用辅助工作目录,方法是使用 rm -r project/src ; git checkout D1 源代码; mv src project/
直接。相反,我更喜欢按照上面所示的方式来做,只是为了 100% 确保一切都非常干净并且始终“可见”。通过这种方式, checkout 操作与我们自己应用的修改完全分开。
从字面上看,这种方式不会出错,而且该方法也适用于所有其他类型的更改。对于重要的更改,假设有人更改了 A
中每个源文件中的每个空格。这种方法使得将其他分支 rebase 到此变得微不足道(如果您也可以将该空白更改放入脚本中)。
关于带有许多移动文件和文件夹的 Git rebase/merge 分支,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41403760/