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

标签 git

我有一个包含两个主要分支的 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 上的其他提交(BC)的更改非常小,如果可以让事情变得更容易,我可以接受丢失它们。

最佳答案

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

前言

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...)

我还假设 AA0 没有任何区别,除了 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/

相关文章:

linux - Git 困惑。 "fatal: failed to open ' app/lang/en/homepage.php': File exists"

git - 传递 git diff 的凭据

git - `git rev-parse branchname`返回的sha1是如何推导出来的

git - 在其历史记录中查找具有给定 merge 的标记修订

Git 的 "Bash.exe"与 "Git Bash.vbs"

git - 打印差异百分比

c++ - 在版本控制中包含外部 C++ 库

混帐 rebase 。我如何使用它来折叠大量的古代提交

git - 整个团队收到 'too many unreachable loose objects' 消息

Git - 在 magento 中找不到匹配版本的包