39272


ある程度コミットログがあるリポジトリをClone後に、コミットログを消して1からログを積み上げているというリポジトリがあります。  
このリポジトリに、Clone元のコミットログを追加（復元？）する方法を探しております。

説明ができているか不安なので、下記にやりたい事の手順を記載致しました。  
不明点などありましたらなるべく早く回答するように致します。  
良い方法がありましたら教えてください。

## 再現手順

  1. Gitでリポジトリ「repo1」を作り、いくつかコミットをした後にGitHubにpushします。
  2. 「repo1」を「repo2」としてcloneし、「.git」を消します。
  3. 「repo2」を再度Git管理します。（git init）
  4. 「repo2」でいくつかコミットを行います。 
    * first commitは「repo1」からcloneした時から変更はありません。
    * 歴史が1から作られます。
  5. 「repo2」に「repo1」のコミットログを追加（復元？）したいです。

## 試したこと

  * 一応以下の手順で復元ができることは確認できましたが、もっと良い方法（簡単な方法）があるのではないかと思っております。
  * 「repo2」のFirst Commitの前に「repo1」のLast Commitを紐付けたいだけなので、方法がありそうだなと思っております。

* * *
[code]

    git clone git@github.com:XXX/repo1.git repo1
    cd repo1
    
    git remote add git@github.com:XXX/repo2.git repo2
    
    git checkout -b repo1_work
    git branch remote/repo2/master repo2_work
    
    git merge -Xtheirs --allow-unrelated-histories repo2_work
    
[/code]


CC BY-SA 3.0
2017-07-28T00:27:43.580
36735
2017-12-04T05:08:08.697
2017-07-28T04:32:22.347
13022
13022
question
git github
Fork後に歴史を消したリポジトリで歴史を復活させたい


# TR; DR

[code]

    # 念のため壊れてもいいレポジトリで
    git replace 新しいレポジトリ最初のコミット 古いレポジトリの最後のコミット
    git filter-branch -- --all
    
[/code]

# 詳細

git replace が利用できそうです。これは何かというと、(おそらく任意の)コミットの sha
を指定したときに取得できる中身を、別のオブジェクトの中身から取得するようにするコマンドです。

具体例として、以下で作成されるレポジトリ repo1, repo2 があるとします。

[code]

    rm -rf repo1 repo2
    
    mkdir repo1
    ( cd repo1
      git init
      echo hoge > hoge
      git add hoge
      git commit -m "Initial"
      echo fuga >> hoge
      git add hoge
      git commit -m "Append fuga" )
    
    git clone repo1 repo2
    ( cd repo2
      rm -rf .git
      git init
      git add -A
      git commit -m "Re-initialize"
      echo piyo >> hoge
      git add hoge
      git commit -m "Append piyo" )
    
    ( cd repo2
      git remote add repo1 ../repo1
      git fetch -p repo1 )
    
    ( cd repo1
      git log --graph > ../repo1-before.txt
    )
    
    ( cd repo2
      git log --graph > ../repo2-before.txt
    )
    
[/code]

### repo1-before.txt

[code]

    * commit 87ee5eb689e4aa33c4b6816c501d89ee154658ea
    | Author: Yuki INOUE <my.mail@domain.com>
    | Date:   Fri Nov 3 11:47:18 2017 +0000
    |
    |     Append fuga
    |
    * commit 7706f3beea43965c3dd92a9fcc914bbe4f91efbf
      Author: Yuki INOUE <my.mail@domain.com>
      Date:   Fri Nov 3 11:47:18 2017 +0000
    
          Initial
    
[/code]

### repo2-before

[code]

    * commit 59a6096bdad4da18b1055fc66f49e4d54bc05be4
    | Author: Yuki INOUE <my.mail@domain.com>
    | Date:   Fri Nov 3 11:47:18 2017 +0000
    |
    |     Append piyo
    |
    * commit 3fd04fd77a62b2f5471902eb0f020ade791c598c
      Author: Yuki INOUE <my.mail@domain.com>
      Date:   Fri Nov 3 11:47:18 2017 +0000
    
          Re-initialize
    
[/code]

git レポジトリ上で `git replace sha_id content_sha_id` を実行すると、 `sha_id` の中身は、
`content_sha_id` の中身から取得するようになります。これは、このコマンドを実行したローカルレポジトリのみで有効です。

[code]

    repo1_end=$(
        cd repo1
        git rev-parse HEAD )
    
    repo2_init=$(
        cd repo2
        git rev-list --max-parents=0 HEAD )
    
    ( cd repo2
      git replace $repo2_init $repo1_end
    )
    
    # repo2 では、一時的に、 `.git/info/replace` が書き換えられ、
    # repo2_init が repo1_end で解決されている。
    
    ( cd repo2
      git log --graph > ../repo2_replaced.txt # 確認する。
    )
    
[/code]

### repo2_replaced

[code]

    * commit 59a6096bdad4da18b1055fc66f49e4d54bc05be4
    | Author: Yuki INOUE <my.mail@domain.com>
    | Date:   Fri Nov 3 11:47:18 2017 +0000
    |
    |     Append piyo
    |
    * commit 3fd04fd77a62b2f5471902eb0f020ade791c598c
    | Author: Yuki INOUE <my.mail@domain.com>
    | Date:   Fri Nov 3 11:47:18 2017 +0000
    |
    |     Append fuga
    |
    * commit 7706f3beea43965c3dd92a9fcc914bbe4f91efbf
      Author: Yuki INOUE <my.mail@domain.com>
      Date:   Fri Nov 3 11:47:18 2017 +0000
    
          Initial
    
[/code]

git の log を見て、問題がなければ、 `git filter-branch` を実行して、 replace
を解決した形でコミットを実際に書き換えます。 これによって、 replace が解決された形でコミットが再生成されます。この状態になると、 push
ができます。

[code]

    # 問題なければ確定する
    ( cd repo2
      git filter-branch -- --all
      git log --graph > ../repo2_rewritten.txt
      git push repo1 master:repo2-master
    )
    
    ( cd repo1
      git log --graph repo2-master > ../repo1_new_master.txt
    )
    
[/code]

### repo1_new_master, repo2_rewritten (同じ内容)

[code]

    * commit 0477c8800097110a858834f5711b2fcee1380cbc
    | Author: Yuki INOUE <my.mail@domain.com>
    | Date:   Fri Nov 3 11:47:18 2017 +0000
    |
    |     Append piyo
    |
    * commit 87ee5eb689e4aa33c4b6816c501d89ee154658ea
    | Author: Yuki INOUE <my.mail@domain.com>
    | Date:   Fri Nov 3 11:47:18 2017 +0000
    |
    |     Append fuga
    |
    * commit 7706f3beea43965c3dd92a9fcc914bbe4f91efbf
      Author: Yuki INOUE <my.mail@domain.com>
      Date:   Fri Nov 3 11:47:18 2017 +0000
    
          Initial
    
[/code]

この作業は、レポジトリのレビジョンの参照方法を途中で書き換えるので、壊れてもいいローカルレポジトリを用意して作業し、何かおかしくなってしまったら、レポジトリごと捨て去るのがいいと思います。


CC BY-SA 3.0
2017-11-03T11:59:22.823
39272
2017-11-03T12:31:05.757
2017-11-03T12:31:05.757
754
754
36735
answer