在Git中的根提交之前插入NON-EMPTY提交?

问题描述 投票:0回答:1

我有问题,请多多指教!我有一个现有的git repo,出于各种原因(我不会在这里讨论),我正在尝试创建一个ROOT提交

说这是我的git提交历史记录:

(ROOT) C1 <-C2 <-C3 <-C4 <-C5   <--branchname (HEAD)

我想在C1之前添加一个初始提交(CX,它不是空的)。所以它应该像这样结束:

(NEW ROOT) CX-C1 <-C2 <-C3 <-C4 <-C5   <--branchname (HEAD)

我在这里找到了类似的问题:Insert a commit before the root commit in Git?但这是为了在现有根之前附加一个EMPTY git commit。我还在这里尝试了答案中的步骤:https://stackoverflow.com/a/9736098/11491070进行了一次更改:我将git commit --allow-empty -m 'initial'替换为git add .; git commit -m "initial laravel commit"; git push;,然后执行了重新设置步骤:git rebase --onto newroot --root master失败,并出现TON合并冲突:

First, rewinding head to replay your work on top of it...
Applying: add initial quickadminpanel, with admin intrface and APIs for tags. Also added (but not yet enabled) ajax datatables module
Using index info to reconstruct a base tree...
.git/rebase-apply/patch:4537: trailing whitespace.
     * 
.git/rebase-apply/patch:4539: trailing whitespace.
     * 
.git/rebase-apply/patch:4547: trailing whitespace.
     * 
warning: 3 lines add whitespace errors.
Falling back to patching base and 3-way merge...
CONFLICT (add/add): Merge conflict in webpack.mix.js
Auto-merging webpack.mix.js
CONFLICT (add/add): Merge conflict in routes/web.php
Auto-merging routes/web.php
CONFLICT (add/add): Merge conflict in routes/api.php
Auto-merging routes/api.php
CONFLICT (add/add): Merge conflict in resources/views/welcome.blade.php
Auto-merging resources/views/welcome.blade.php
CONFLICT (add/add): Merge conflict in resources/sass/app.scss
Auto-merging resources/sass/app.scss
CONFLICT (add/add): Merge conflict in resources/sass/_variables.scss
Auto-merging resources/sass/_variables.scss
CONFLICT (add/add): Merge conflict in resources/lang/en/validation.php
Auto-merging resources/lang/en/validation.php
CONFLICT (add/add): Merge conflict in resources/lang/en/passwords.php
Auto-merging resources/lang/en/passwords.php
CONFLICT (add/add): Merge conflict in resources/lang/en/pagination.php
Auto-merging resources/lang/en/pagination.php
CONFLICT (add/add): Merge conflict in resources/lang/en/auth.php
Auto-merging resources/lang/en/auth.php
CONFLICT (add/add): Merge conflict in resources/js/bootstrap.js
Auto-merging resources/js/bootstrap.js
CONFLICT (add/add): Merge conflict in resources/js/app.js
Auto-merging resources/js/app.js
CONFLICT (add/add): Merge conflict in package.json
Auto-merging package.json
CONFLICT (add/add): Merge conflict in database/seeds/DatabaseSeeder.php
Auto-merging database/seeds/DatabaseSeeder.php
CONFLICT (add/add): Merge conflict in database/migrations/2014_10_12_100000_create_password_resets_table.php
Auto-merging database/migrations/2014_10_12_100000_create_password_resets_table.php
CONFLICT (add/add): Merge conflict in database/factories/UserFactory.php
Auto-merging database/factories/UserFactory.php
CONFLICT (add/add): Merge conflict in database/.gitignore
Auto-merging database/.gitignore
CONFLICT (add/add): Merge conflict in config/services.php
Auto-merging config/services.php
CONFLICT (add/add): Merge conflict in config/logging.php
Auto-merging config/logging.php
CONFLICT (add/add): Merge conflict in config/database.php
Auto-merging config/database.php
CONFLICT (add/add): Merge conflict in config/cache.php
Auto-merging config/cache.php
CONFLICT (add/add): Merge conflict in config/broadcasting.php
Auto-merging config/broadcasting.php

如何解决此问题?请帮助!

git version-control rebase git-rebase
1个回答
1
投票

[首先,请注意:您已将存储库向前拉。 Git会倒退它们。将根提交last(即左侧)和latest >>提交first(即右侧)放入]:>

C1 <-C2 <-C3 <-C4 <-C5   <--branchname

分支名称始终包含最新

提交的哈希ID。这就是Git如何知道最新的一个。 Git使用C5查找C4,因为提交C5本身具有唯一的哈希ID,contains就是提交C4的唯一哈希ID。同时C4保留C3的哈希ID,依此类推; C2拥有C1的唯一哈希ID,C1 根提交因为内部没有父哈希ID。第二,实际上不能更改任何提交。因此,您将在此处执行

not

“ change commit C1”-您和Git都无法执行此操作-而是进行一个新的提交,即C1'C21或我们要调用的任何内容。在进行此新提交之前,我们需要另一个新提交CX,它是一个根提交并包含所需的内容。

可以

使用Antony Hatchkins's answer中的方法,但是如今,这样做的方法是从git checkout --orphan开始(而不是棘手的符号引用命令):
git checkout --orphan newroot git rm -rf --cached . # same as before <arrange work tree as desired> # same as before git add . # or git add each file, same as before git commit # same as before
这是创建提交CX的操作序列,因此我们具有:

C1--C2--C3--C4--C5 <-- master CX <-- newroot

现在我们进入最有趣的部分。使用git rebase是错误的方法。

因为

通过选择樱桃进行重新设置工作。这会将提交C1转换为对每个文件的[[add请求–提交C1是根提交,将其与empty tree进行比较以查看发生了什么更改,并且如您所见,这导致您在C1中已经添加的每个文件中的添加/添加冲突。您必须在这里回答的问题-我不能为您回答-是:您想要在新的CX副本中想要什么[[0],类似于C1,但它具有C1作为其父项?最后,我们将拥有:

CX

在我们的存储库中。如果在C1--C2--C3--C4--C5 [abandoned] CX--C1'-C2'-C3'-C4-C5' <-- master 的哈希ID上运行git checkout,是否应该像在C1'的哈希ID上运行git checkout一样看到相同内容?这两个提交将具有不同的哈希ID,但是作者和提交者,时间戳和日志消息相同,依此类推。如果它们也应该具有相同的
tree
(快照),则使用C1git replace可以轻松完成工作。这是基本的食谱:

git filter-branch((此时您可以运行git replace --graft <hash-of-C1> newroot 以确保它看起来正确)。然后运行:git log

(假设您只希望复制git filter-branch -- master
中的提交,并更新参考master)。无操作筛选器分支(未指定筛选器)以正确的顺序(即,向前,即向Git的后退)复制每个可到达的提交,先复制master,然后复制C1,依此类推,但是—至关重要的是-

遵守替换指令

。所以现在我们有了这个:
C2

如果这是理想的最终结果,我们现在只需要删除C1--C2--C3--C4--C5 refs/original/refs/heads/master CX <-- refs/replace/<hash-of-C1> \ C1'-C2'-C3'-C4-C5' <-- master 名称和不再有用的refs/original/名称:

refs/replace/<hash-of-C1>
您的历史记录现在已被重写。所有

old

克隆都必须销毁(或者至少应该停止使用它们),因为它们中的哈希ID是
original
提交的哈希ID,而您不想重生使生活变得悲惨。更新后的克隆中废弃的C1至C5是无害的:它们可以以废弃状态留在那里,直到Git's Grim

Reaper

Collector git update-ref -d refs/original/refs/heads/master git update-ref -d refs/replace/<hash-of-C1> 到处乱扔垃圾为止。
© www.soinside.com 2019 - 2024. All rights reserved.