在Git中提交根提交之前添加提交?

时间:2013-05-26 18:02:50

标签: git github backup commit

新问题

两个问题:

  1. 我正在尝试在所有提交之前进行提交 最底层的提交以660fb2a76211f36ec9a67d0454a90eab469e9fd0为SHA。当我每次提交都输入git rebase -i 660fb2a76211f36ec9a67d0454a90eab469e9fd0但最后一次显示在列表中时 我真的需要这个提交出现,所以我可以把第一个提交作为最后一个提交!

  2. 当我把第一个提交作为第一个提交在列表中时(意味着总共第二个提交,因为第一个提交不在上面提到的列表中)我收到一个错误: error: could not apply b722c76... v1.4.3 BEAT release
    我只是将它从列表的底部切下来并把它放到顶部! 我没有更改号码!
    我也试了好几次。同样的结果。

  3. 到目前为止。如果您有问题请继续问问!

    原始问题

    我刚刚发现了我项目的旧备份。这些备份是在我使用git之前创建的 我现在想将它们作为旧提交添加到我的存储库中。这意味着我必须将这些提交放在所有其他提交之前。

    现在有几个问题:

    1. 我如何在其他人之前提交提交?
    2. 我怎么能这么快? (我有很多备份!)
    3. 如何为这些 “旧” 提交设置日期? (我知道备份的日期!)
    4. 如果不清楚,请提及。我会解决这个问题!

      最后一件事:

      我已经在GitHub上发布了这个。我主要使用他们的软件来提交提交。那么如何将其推回GitHub呢?

2 个答案:

答案 0 :(得分:12)

更新

我使用git rebase--root标志找到了另一种稍微简单的方法。我用我的回购邮件试了一下,所以我知道它有效(至少对于一个完全 线性 历史,最后更多关于它)。

步骤1:创建repo的备份克隆

让我们安全地进行备份,以防我们最终做出灾难性的事情并丢失您的数据:

git clone original-repo backup-repo

第2步:创建孤立分支(这将是您的新根)

签出孤儿分支。指定起始点提交/分支是可选的,如果你保留该参数,那么Git将默认使用你当前的提交作为起点(它遵循标准分支语法的模式):

git checkout --orphan new-master firstCommitOfOldMaster

我将旧主服务器的根目录指定为起点,因为它可能会更快地执行以下步骤(删除工作目录文件)。

第3步:删除工作目录文件

从旧主服务器创建孤立分支new-master可能会在工作目录和索引中留下文件,具体取决于您分支的提交中文件的状态:

  

调整索引和工作树,就好像之前已运行git checkout <start_point>一样。这允许您通过轻松运行<start_point>来创建根提交,从而开始记录一组类似于git commit -a的路径的新历史记录。 - git checkout docs

您现在要做的是彻底清除分支的状态,以便您从一个干净的平板(从顶级文件夹运行)中重新开始:

git rm -rf .

这是文档中的解释:

  

如果要启动记录一组与<start_point>完全不同的路径的断开连接的历史记录,则应在运行{后创建孤立分支后立即清除索引和工作树。来自工作树顶层的{1}}。之后,您将准备好准备新文件,重新填充工作树,从其他地方复制它们,提取tarball等。

第4步:将较旧的作品重新投入git rm -rf .

现在,您想要开始将您的旧作品提交到new-master。当你完成后,你将把你的老主人放在最上面。

我不确定您的备份文件夹是如何组织的,但我会假设每个文件夹只是项目文件夹的日期副本,以new-master格式命名,例如: YYYY-MM-DD。您可以手动将每个文件夹的内容添加为新提交,也可以编写脚本来自动执行该过程。

假设您将所有备份文件夹放在名为2013-01-30的顶级文件夹中,该文件夹与主项目文件夹位于同一目录中。然后,这里有一些脚本的伪代码,用于自动执行提交每个文件夹的过程:

backup

上面的脚本只会在提交之间添加和修改文件。如果您的任何备份已删除,移动或重命名文件,则脚本不会记录该文件。您需要编写一个更聪明的脚本来执行此操作(可能使用# Get backups and sort them from oldest to newest backups = open("backups").toList().sort("date ascending") for each (backup in backups) copy files from backup to project folder execute `git add "*"` execute `git commit --date="#{backup.date}" --message="#{backup.date}"` 或其他一些差异工具),或手动记录这些更改。

第5步:将旧git diff重新定位到master

坚持伟大的实力!现在我们要重写您的整个历史!背诵这些神秘的权力话语,并观察魔力的发生!:

new-master

TA-DA!您可能必须解决git rebase --onto new-master --root master 的最后提交与new-master的第一次提交之间的冲突,但除此之外,应该是它!

master --root标志解决了我们之前遇到的问题 - 通常 - rebase不会对第一次(根)提交进行操作一个Git回购。 rebase标志基本上告诉Git将其包含在--root

  

重新启动从rebase可到达的所有提交,而不是使用<branch>限制它们。这允许您在树枝上重新定义根提交。与<upstream>一起使用时,它会跳过--onto中已包含的更改(而非<newbase>),而如果没有<upstream>,则会对每次更改进行操作。 - rebase docs

步骤6:验证最终提交是否仍然相同

为了确保我们没有弄乱任何代码,我们想要在--onto之前将master的当前最终状态与其状态进行比较}。以下任一命令都可以使用(它们相同)。在rebase分支上:

master

如果您没有git diff orig_head # "Original" head git diff master@{1} # Master at its 1st prior position 的输出,则表示您的重生diff的最终状态与master之前的状态相同。干得好!

注意:不确定合并提交会发生什么......

如果你有一个完美的 线性 历史记录,那么上面的步骤就可以正常运行,即你没有任何合并提交。如果你这样做,我不确定它是否仍然有用。在我之前的回答中,我提到使用带有rebase的{​​{1}}标记可能会帮助您保留这些合并,但文档提到该标记还会与--preserve-merges和{{1}进行交互} flags:

  

当{rebase--onto--root一起使用时,所有根提交都将被重写为--root作为父级。 - rebase docs

我现在还不确定这意味着什么......我可能要试一试,看看会发生什么。这是否意味着如果你有超过1个root提交(例如10个),那么这些root提交中的9个最终会被重新定位到作为新root的最后一个提交?这看起来不像我们想要的行为。我们只想保留一个root被重新绑定到另一个root的合并提交。


以前的回答

MGA有the right idea with rebase。我不确定这是否能解决您的问题,但是您可能需要在您的仓库中进行新的根提交,将备份文件添加为新的提交,然后在旧的提交图上重新设置。< / p>

例如,根据the documentation--onto有一个--preserve-merges标记:

  

<强> <newbase>
  创建一个名为git checkout的新孤立分支,从--orphan开始并切换到它。在这个新分支上进行的第一次提交将没有父级,它将成为与所有其他分支和提交完全断开的新历史的根。

所以也许你可以试试

--orphan <new_branch>

然后将备份文件提交给它。然后签出<new_branch>,执行

<start_point>

我认为您可能需要git checkout --orphan <temp_branch> 第一次提交,因为temp_branch的第二个参数是您要重新绑定的分支的旧基础(在本例中为git cherry-pick <first commit from master> git rebase --onto temp_branch <first commit from master> master ),并且不包括旧基地。这就是为什么我认为你需要cherry-pick来获取它,因为它本身没有基本提交,所以你不能在rebase --onto中为它指定一个

另请注意,如果您的提交历史记录不是线性的(即它具有合并提交),那么master通常不会保留它们。它有一个cherry-pick标志,但我之前从未使用它,所以我不确定它是如何工作的。来自the docs

  

<强> rebase
  的 rebase
  而不是忽略合并,尝试重新创建它们。

     

这在内部使用--preserve-merges机制,但明确地将它与-p选项结合使用通常不是一个好主意,除非你知道你在做什么(见下面的BUGS)。

那么,也许所有这些都有效?

答案 1 :(得分:3)

1)您可以使用git rebase。在这种情况下,您可以执行以下操作:

首先,提交旧的更改。然后:

$ git rebase --interactive master

这将在文本编辑器中打开您的提交文件。只需更改提交的顺序(将最后提交的剪切/粘贴作为第一个提交,包括左侧的“选择”命令),保存并关闭编辑器。 此时,rebase将开始。要在确认时继续,请键入:

$ git rebase --continue

直到全部完成。更多信息here

2)我不知道任何方法可以让它更快,但它应该已经非常快了。

3)要更改提交日期,您必须更改GIT_AUTHOR_DATE和GIT_COMMITTER_DATE。 为此,有一个很好的例子in the accepted answer for this StackOverflow question

希望它有所帮助!