如何在我在github.com上分叉的项目上重新播放本地Git存储库的提交?

时间:2009-09-21 22:34:13

标签: git github

是的,我知道我应该从一开始就分配项目,但这就是我现在所处的情况。 :)

我有一个本地Git存储库,其中包含我的博客,在我的本地计算机上,有几个月的提交历史记录。最初,我只是从存储库下载文件 http://github.com/mojombo/mojombo.github.com,我继续使用我的本地Git存储库,第一次提交看起来像mojombo存储库中的最新文件。

我现在想要分叉项目并让我的本地Git存储库提交在它上面重放,所以看起来我从头开始分叉项目,然后将它推回到mojombo的存储库的分叉版本,在我的GitHub帐户上:

http://github.com/program247365/mojombo.github.com

所以历史可能就像这样:

mobjombo repository:         1---2---3----23
                                  \
my blog repository commits:       24---25---

我可以使用哪些Git命令来完成此操作?

我看过this question。我是否必须将mojombo的存储库添加为我的项目的远程,然后将其拉入,合并,解决冲突,然后在GitHub上推送到我的分叉项目?

3 个答案:

答案 0 :(得分:14)

简而言之:

一种解决方案是使用移植来连接历史记录,然后使用 git filter-branch 根据这些移植重写历史记录,然后选择执行合并

请注意,在原始存储库( rebase 解决方案)中的新开发之上重放您的更改(您的提交)的解决方案是另一种可行的解决方案。


更长版本:

让我们假设您要么记住,要么通过检查源和/或使用git命令找到您下载快照的存储库的修订版,并开始本地开发。我们将此修订版本称为START或A.

假设您本地断开连接的历史记录位于原始存储库的克隆中。这意味着本地断开连接的开发与项目的完整历史记录位于同一存储库中。假设您的本地分支位于分支“master”中(为简单起见,只有一个分支)。

如果您没有使用本地断开连接的工作将项目提取到存储库中,则可以使用以下命令执行此操作:

$ git remote add origin git://github.com/mojombo/mojombo.github.com.git
$ git fetch origin

历史看起来如下:

*---*---*---*---*---A---*---*---*---*      <--- origin/master (remote-tracking branch)

                                     x---y---*---*---*      <--- master (your local disconnected history)

上图中名为A的提交是您作为快照下载的START提交,并启动了本地开发。

有两种可能性:您将“A”的快照作为初始提交“x”,或者您首次提交的是您的本地修改。

在第一种情况下(您提交了原始启动状态,例如“初始提交”或“导入”),您希望连接的历史记录如下所示:

*---*---*---*---*---A---*---*---*---*      <--- origin/master (remote-tracking branch)
                                      \
                                        \-y---*---*---*       <--- master (your local disconnected history)

即。你的第一个原始提交'y'将'A'作为父母。

在第二种情况下(您提交了更改),您希望连接的历史记录看起来像这样:

*---*---*---*---*---A---*---*---*---*           <--- origin/master (remote-tracking branch)
                                      \
                                        \-x---y---*---*---*      <--- master (your local disconnected history)

即。你想首先提交'x'让'A'作为父母。

在这两种情况下,您都希望找到提交'A'的完整SHA-1标识符,以及提交'x'和'y'的完整SHA-1标识符。

您可以使用git rev-parse找到提交'A'的SHA-1(假设您已经不知道):

$ git rev-parse A     # or A^{commit}
437b1b20df4b356c9342dac8d38849f24ef44f27

(可能需要'^ {commit}'后缀以确保您找到 commit SHA-1,如果您通过其标记知道'A',这很重要,例如' v0.99';在您的情况下没有必要,因为有问题的存储库不使用标签)。

你可以使用git rev-list找到提交'x'和'y'的SHA-1(假设您的开发是在分支'master'上完成的):

$ git rev-list --topo-order master | tail -2
8bc9a0c769ac1df7820f2dbf8f7b7d64835e3c68
e83c5163316f89bfbde7d9ab23ca2e25604af290

(“| tail -2”用于查找生成列表中的最后两个提交;如果没有,则不需要使用它。)

注意: 以上所有示例中,完整的SHA-1都是示例,不应按原样使用!

让我们将您希望将“A”(或“START”)作为父级的提交命名为FIRST(它将是“x”或“y”,具体取决于您的情况,如上所述)。现在我们使用移植机制连接历史记录:

$ echo "<SHA-1 of FIRST> <SHA-1 of START>" > .git/info/grafts

然后你应该检查你现在是否已正确连接(加入)历史记录,使用gitk或QGit等图形历史记录浏览器,或GitX是否在MacOS X上,甚至是“git log --graph”,或者“git show-branch”,例如:

$ gitk master origin/master    # or --all

(其中gitk仅作为示例;如果您使用“git show branch”,则不能总是使用“--all”选项。

最后,我们可能希望将这些更改永久化,因此任何从我们的存储库获取的人都会有连接历史记录。我们可以使用git filter-branch

来完成此操作
$ git filter-branch master

您将在'refs / original / master'中拥有原始(断开连接)历​​史记录。

现在您可以删除移植文件:

$ rm .git/info/grafts

现在,您可以在原始存储库的新开发中合并:

$ git merge origin/master

设置每个分支的配置,这样就足以在分支'master'上执行简单的“git pull”来拉动(合并)origin(al)存储库中的更改留给读者练习。 。: - )


注意: rebase解决方案会产生以下历史记录(假设我们有第一个comit简单导入的情况):< / p>

*---*---*---*---*---A---*---*---*---*                                      <--- origin/master (remote-tracking branch)
                                                                     \
                                                                       \-y'---*'---*'---*'      <--- master (your local disconnected history)

(其中y'表示修改了提交y:它应该是相同的变更集,但它与提交不同。

答案 1 :(得分:5)

当我尝试git pull时,它给了我以下错误:

$ git pull grid master:master
! [rejected]        master     -> master  (non fast forward)

在我的特定情况下,似乎git rebase是我的方式,如下面的步骤所示:

#Clone my forked project from github
git clone git@github.com:program247365/mojombo.github.com.git 

#Add my repo as a remote repo, with the alias 'grid'
git remote add grid "path/to/remote/gitrep/with/all/history/unrelated/to/mojombo/" 

#Rebase my commits on top of mojombo's
git rebase master grid/master

#Switch to the local master branch 
git checkout master

#Call up my mergetool via git, to start rectifying the conflicts that emerge between my repo, and mojombo's
git mergetool

#Push my rebased/combined repo back to Github.com
git push github

答案 2 :(得分:4)

这是一个关于你能做什么的想法。这与您在问题底部总结的想法相反。

  1. 叉子mojombo在GitHub的回购。
  2. 克隆你的分叉副本。
  3. 合并您现有(原始)存储库中的更改。
  4. 删除原始存储库(如果需要,但您不再需要它了。)
  5. 所以基本上,在GitHub上分叉后,您可以使用以下命令序列:

    $ git clone git://github.com/$YOUR_USERNAME/$YOUR_PROJECT.git  # Clone your GitHub fork (#2 from above)
    $ git pull /path/to/your/original/repo master:master           # Clone your original repo's master branch into your new repo (cloned from GitHub)
    $ rm -rf /path/to/your/original/repo                           # Might as well delete the original -- you don't need it anymore, since all your history is in your new repo
    

    总之,这种方法将合并您在旧版回购中所做的所有更改(从而保留您的开发历史记录),同时还会提取mojombo的历史记录,可让您跟上如果适用的话,mojombo的变化/很容易将变化反馈给他的回购。