19

新问题

两个问题:

  1. 我试图在所有提交之前提交一个提交。
    最底部的提交具有660fb2a76211f36ec9a67d0454a90eab469e9fd0SHA。当我键入git rebase -i 660fb2a76211f36ec9a67d0454a90eab469e9fd0每个提交但最后一个提交显示在列表中时。
    我真的需要这个提交出现,所以我可以把第一个提交放在最后!

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

到目前为止就是这样。如果您有问题,请继续提问!

原始问题

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

现在有几个问题:

  1. 我通常如何将提交放在其他提交之前?
  2. 我怎么能这么快?(我有很多备份!)
  3. 如何为这些“旧”提交设置日期?(我知道备份的日期!)

如果有不清楚的地方,请提出。那我就解决这个问题!

最后一件事:

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

4

2 回答 2

14

更新

--root我找到了另一种稍微简单的方法,使用git rebase. 我用我的一个 repo 进行了尝试,所以我知道它有效(至少对于完全线性的历史,最后更多)。

第 1 步:创建存储库的备份克隆

让我们谨慎行事并进行备份,以防万一我们最终做出灾难性的事情并丢失您的数据:

git clone original-repo backup-repo

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

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

git checkout --orphan new-master firstCommitOfOldMaster

我将旧 master 的根指定为起点,因为它可能会使以下步骤更快(删除工作目录文件)。

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

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

索引和工作树的调整就像您之前运行过一样git checkout <start_point>。这允许您开始一个新的历史记录,该历史记录记录一组类似于<start_point>通过轻松运行git commit -a以进行根提交的路径。— git checkout 文档

您现在要做的是完全清除分支的状态,以便您真正从一个干净的状态重新开始(从顶级文件夹运行):

git rm -rf .

这是来自文档的解释:

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

第 4 步:将旧工作重新提交到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}"`

上面的脚本只会在提交之间添加和修改文件。如果您的任何备份被删除、移动或重命名,脚本将不会记录这些。您需要编写一个更聪明的脚本来做到这一点(可能是利用git diff或其他一些差异工具),或者手动记录这些更改。

第 5 步:将旧的变基masternew-master

看看 Git 的强大功能吧! 现在我们将改写您的整个历史! 背诵这些神秘的力量话语,并观看魔法发生!:

git rebase --onto new-master --root master

达达!您可能需要解决 的最后一次提交new-master和第一次提交之间的冲突master,但除此之外,应该就是这样!

解决我们之前遇到的问题的--root标志- 通常 -不会在 Git 存储库的第一次(根)提交上运行。该标志基本上告诉 Git 将其包含在:rebaserebase--rootrebase

重新设置所有可从 到达的提交<branch>,而不是用<upstream>. 这允许您在分支上重新设置根提交。当与 一起使用时--onto,它将跳过已经包含在<newbase>(而不是<upstream>)中的更改,而没有--onto它将对每个更改进行操作。—变基文档

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

只是为了确保我们没有弄乱任何代码,我们需要在master执行rebase. 以下任一命令都将起作用(它们是相同的)。在master分支上时:

git diff orig_head   # "Original" head
git diff master@{1}  # Master at its 1st prior position

diff如果您没有masterrebase. 好工作!

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

现在,如果您有完美的线性历史记录,即您没有任何合并提交,上述步骤将可以正常工作。我不确定如果你这样做它是否仍然有效。在下面我之前的回答中,我提到使用--preserve-merges标志 withrebase可能会帮助您保持这些合并,但文档提到该标志也与--ontoand--root标志交互:

当 [ is] 与and--root一起使用时,所有根提交将被重写为具有父级。—变基文档--onto--preserve-merges<newbase>

目前我不确定这意味着什么……我可能必须尝试一下,看看会发生什么。这是否意味着如果您有超过 1 个根提交(例如 10 个),那么这些根提交中的 9 个最终将重新定位到作为新根的最后一个?这似乎不是我们想要的行为。我们只想保留一个根被重新定位到另一个根的合并提交。


上一个答案

MGA的想法是正确的rebase。我不确定这是否会解决您的问题,但也许您需要在您的存储库中进行新的根提交,将您的备份文件作为新提交添加到它之上,然后在顶部重新设置您的旧提交图。

例如,根据文档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它才能得到它,因为它本身没有基本提交,所以你不能在rebase.

另请注意,如果您的提交历史不是线性的(即它具有合并提交),那么rebase通常不会保留这些。它有一个--preserve-merges标志,但我以前从未使用过它,所以我不太确定它会如何工作。从文档

-p
--preserve-merges
不要忽略合并,而是尝试重新创建它们。

这在内部使用了机器,但是除非您知道自己在做什么(请参阅下面的错误),否则--interactive将其与选项显式结合通常不是一个好主意。--interactive

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

于 2013-05-26T23:11:04.057 回答
3

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

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

$ git rebase --interactive master

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

$ git rebase --continue

直到一切都完成。更多信息在这里

2)我不知道有什么方法可以让它更快,但它应该已经相当快了。

3) 要更改提交日期,您必须更改 GIT_AUTHOR_DATE 和 GIT_COMMITTER_DATE。为此,在这个 StackOverflow question 的接受答案中有一个很好的例子。

希望能帮助到你!

于 2013-05-26T19:31:42.020 回答