带有许多移动文件和文件夹的 Git rebase/merge 分支

Mat*_*son 3 git

我有一个包含两个主要分支的 Git 存储库:master 和 dev。它目前看起来像这样:

master  ( )----( )----(A)----(B)----(C)
                \
                 \
dev              ( )----( )----( )----( )----(~ 30 additional commits...)
Run Code Online (Sandbox Code Playgroud)

非常简单,除了master上的 commit A包含对文件和文件夹结构的重大更改(基本上,我使用此处显示的步骤将存储库在层次结构中向上移动了一层)。

我想继续在 dev 分支上工作,但是当我尝试将 dev 变基到 master 以将新的文件结构引入 dev 时,Git 出现了大量错误。我git reset回到了一个理智的状态,但在我(有些有限)的 Git 经验中,许多错误通常意味着我采取了错误的方法。

有没有更好的方法将重新组织的文件夹结构转移到 dev 分支?如果有帮助,主(BC)上的其他提交中的更改非常小,如果丢失它们会使事情变得更容易,我可以接受。

Ano*_*noE 12

是的,有一种理智的方法可以做到这一点。

前言

master 现在是(如果我理解正确的话):

project
   src
     file.c
Run Code Online (Sandbox Code Playgroud)

dev是,因为它不包含 commit A

src
  file.c         # with some changes
Run Code Online (Sandbox Code Playgroud)

你的分支是这样的:

master  ( )----(A0)----(A)----(B)----(C)
                \
                 \
dev              (D1)----(D2)----(D3)----( )----(~ 30 additional commits...)
Run Code Online (Sandbox Code Playgroud)

我还假设除了被插入到所有文件路径中(根据您链接的问题,“将您的树向上移动”到新的根目录中)之外,没有任何A区别。A0project/project

我们开始做吧...

我们在每一步都做我们git rebase内部会做的事情,同时git有点愚弄,通过做我们自己的“挑选”步骤而不是自己git做的事情。

我们使用第二个工作目录。$WD1是原始工作目录的绝对路径,$WD2是其他一些绝对路径(除此之外)。

首先,创建您的助手目录作为原始目录的克隆:

cd $WD2
git clone $WD1 dev .
Run Code Online (Sandbox Code Playgroud)

然后,启动一个newdev最终将dev基于A.

cd $WD1
git checkout A
git checkout -b newdev
Run Code Online (Sandbox Code Playgroud)

我们在不给任何机会把它搞砸的情况下D1提交:newdevgit

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`"
Run Code Online (Sandbox Code Playgroud)

现在的情况是:

newdev                       (D1')     
                           /
                         /
master  ( )----(A0)----(A)----(B)----(C)
                \
                 \
dev              (D1)----(D2)----(D3)----( )----(~ 30 additional commits...)
Run Code Online (Sandbox Code Playgroud)

现在,重复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`"
Run Code Online (Sandbox Code Playgroud)

现在的情况是:

newdev                       (D1')----(D2')     
                           /
                         /
master  ( )----(A0)----(A)----(B)----(C)
                \
                 \
dev              (D1)----(D2)----(D3)----( )----(~ 30 additional commits...)
Run Code Online (Sandbox Code Playgroud)

重复直到完成。

当然,您需要为这些命令创建一个小的 shell 脚本,它会遍历所有提交D1 ... D30

之后,一个简单的git rebase master将像往常一样执行从A到的变基C。然后,newdev通过更改名称来摆脱:

git checkout newdev
git branch olddev dev         # just in case...
git branch -D dev
git checkout -b dev
Run Code Online (Sandbox Code Playgroud)

一般注意事项

为什么是第二个工作目录?

请注意,在这种特殊情况下,可能有一些方法可以通过rm -r project/src ; git checkout D1 src ; mv src project/直接使用来避免二级工作目录。我更喜欢像上面那样做,只是为了 100% 确保一切都非常干净并且始终“可见”。通过这种方式,结帐操作与我们自己应用的修改完全分开。

从字面上看,这种方式不会出错,而且这种方法也适用于所有其他类型的更改。对于重要的更改,假设有人更改了A. 这种方法使得将其他分支变基到此变得微不足道(如果您也可以将该空白更改放入脚本中)。