web-dev-qa-db-ja.com

サブディレクトリを別のGitリポジトリにデタッチ(移動)します

私は Git リポジトリを持っていて、そこにはたくさんのサブディレクトリがあります。今、私はサブディレクトリの1つが他と無関係であり、別々のリポジトリにデタッチされるべきであることを発見しました。

サブディレクトリ内のファイルの履歴を保持しながらこれを行うにはどうすればよいですか?

私はクローンを作成し、各クローンの不要な部分を削除することができたと思いますが、古いリビジョンなどをチェックアウトするときにこれで完全なツリーが得られると思います。 2つのリポジトリには共有履歴がありません。

わかりやすくするために、次のような構造になっています。

XYZ/
    .git/
    XY1/
    ABC/
    XY2/

しかし、私は代わりにこれを望みます:

XYZ/
    .git/
    XY1/
    XY2/
ABC/
    .git/
    ABC/
1665
matli

更新:このプロセスはとても一般的なので、gitチームは新しいツールgit subtreeを使うことでより簡単にしました。こちらを参照してください。 サブディレクトリを別のGitリポジトリにデタッチ(移動)します


リポジトリのクローンを作成してから、git filter-branchを使用して、新しいリポジトリに必要なサブディレクトリ以外のすべてをマークし、ガベージコレクションする必要があります。

  1. ローカルリポジトリを複製するには

    git clone /XYZ /ABC
    

    (注:リポジトリはハードリンクを使用して複製されますが、ハードリンクされたファイルはそれ自体では変更されないため、問題はありません。新しいファイルが作成されます。)

  2. それでは、書き換えたい興味深いブランチを保存してから、Originを削除して、プッシュされないようにし、古いコミットがOriginによって参照されないようにします。

    cd /ABC
    for i in branch1 br2 br3; do git branch -t $i Origin/$i; done
    git remote rm Origin
    

    またはすべてのリモートブランチ用:

    cd /ABC
    for i in $(git branch -r | sed "s/.*Origin\///"); do git branch -t $i Origin/$i; done
    git remote rm Origin
    
  3. サブプロジェクトと関係のないタグも削除したいと思うかもしれません。後でそれを行うこともできますが、リポジトリをもう一度整理する必要があるかもしれません。私はそうしませんでした、そして、すべてのタグのためにWARNING: Ref 'refs/tags/v0.1' is unchangedを得ました(それらはすべてサブプロジェクトと無関係だったので)。さらに、そのようなタグを削除した後、さらに多くのスペースが回収されます。どうやらgit filter-branchは他のタグを書き換えることができるはずですが、私はこれを確認できませんでした。すべてのタグを削除したい場合はgit tag -l | xargs git tag -dを使用してください。

  4. それからfilter-branchとresetを使って他のファイルを除外します。そうすればそれらは整理されます。空のコミットを削除し、タグを書き換えるために--tag-name-filter cat --Prune-emptyを追加しましょう(これは署名を削除する必要があることに注意してください)。

    git filter-branch --tag-name-filter cat --Prune-empty --subdirectory-filter ABC -- --all
    

    あるいは、HEADブランチのみを書き換えてタグや他のブランチを無視するだけの場合もあります。

    git filter-branch --tag-name-filter cat --Prune-empty --subdirectory-filter ABC HEAD
    
  5. その後、バックアップreflogを削除して、スペースを本当に再利用できるようにします(ただし、今では操作は破壊的です)。

    git reset --hard
    git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
    git reflog expire --expire=now --all
    git gc --aggressive --Prune=now
    

    そして今、あなたはABCサブディレクトリのローカルgitリポジトリを持っています。その履歴はすべて保存されています。

注:ほとんどの場合、git filter-branchには実際に追加のパラメーター-- --allが必要です。はい、本当に --space-- all。これはコマンドの最後のパラメータである必要があります。 Matliが発見したように、これはプロジェクトリポジトリとタグを新しいリポジトリに含めます。

編集:たとえば、リポジトリが実際に縮小されていることを確認するために、以下のコメントからのさまざまな提案が組み込まれました(以前はそうではありませんでした)。

1190
Paul

イージーウェイ™

これは非常に一般的で便利なプラクティスであり、gitの大君たちが本当に簡単にできるようになっていますが、gitの新しいバージョン(> = 1.7.11 2012年5月)が必要です。最新のgitをインストールする方法については、appendixをご覧ください。また、下のwalkthroughにはreal-world exampleがあります。

  1. 古いレポを準備する

    pushd <big-repo>
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    popd
    

    注:<name-of-folder>には、先頭または末尾の文字を含めることはできません。たとえば、subprojectという名前のフォルダーは、./subproject/ではなく、subprojectとして渡す必要があります

    Windowsユーザーへの注意:フォルダーの深さが1より大きい場合、<name-of-folder>には* nixスタイルのフォルダー区切り文字(/)が必要です。たとえば、path1\path2\subprojectという名前のフォルダーはpath1/path2/subprojectとして渡す必要があります

  2. 新しいレポを作成する

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. 新しいリポジトリをGithubまたはどこにでもリンクします

    git remote add Origin <[email protected]:my-user/new-repo.git>
    git Push Origin -u master
    
  4. クリーンアップ、必要に応じて

    popd # get out of <new-repo>
    pushd <big-repo>
    
    git rm -rf <name-of-folder>
    

    :これにより、リポジトリ内のすべての履歴参照が残ります。実際にパスワードをコミットしたかどうか、またはファイルサイズを小さくする必要がある場合は、以下の付録を参照してください。 .gitフォルダー。

...

ウォークスルー

これらは上記と同じステップですが、<meta-named-things>を使用する代わりに、リポジトリの正確なステップに従います。

ノードにJavaScriptブラウザーモジュールを実装するためのプロジェクトを次に示します。

tree ~/Code/node-browser-compat

node-browser-compat
├── ArrayBuffer
├── Audio
├── Blob
├── FormData
├── atob
├── btoa
├── location
└── navigator

単一のフォルダーbtoaを個別のgitリポジトリーに分割したい

pushd ~/Code/node-browser-compat/
git subtree split -P btoa -b btoa-only
popd

btoaのコミットのみを持つ新しいブランチbtoa-onlyができました。新しいリポジトリを作成したいと思います。

mkdir ~/Code/btoa/
pushd ~/Code/btoa/
git init
git pull ~/Code/node-browser-compat btoa-only

次に、Githubまたはbitbucketなどに新しいリポジトリを作成し、それをOriginに追加します(ただし、「Origin」は単なる慣習であり、コマンドの一部ではありません。「remote-server」または君が好きなものならなんでも)

git remote add Origin [email protected]:node-browser-compat/btoa.git
git Push Origin -u master

幸せな日!

注:README.md.gitignore、およびLICENSEでリポジトリを作成した場合、最初にプルする必要があります。

git pull Origin -u master
git Push Origin -u master

最後に、大きなリポジトリからフォルダーを削除します

git rm -rf btoa

...

付録

OS Xの最新Git

Gitの最新バージョンを入手するには:

brew install git

OS X用に作成するには:

http://brew.sh

Ubuntuの最新git

Sudo apt-get update
Sudo apt-get install git
git --version

それがうまくいかない場合(ubuntuの非常に古いバージョンがある場合)、試してください

Sudo add-apt-repository ppa:git-core/ppa
Sudo apt-get update
Sudo apt-get install git

それでもうまくいかない場合は、試してください

Sudo chmod +x /usr/share/doc/git/contrib/subtree/git-subtree.sh
Sudo ln -s \
/usr/share/doc/git/contrib/subtree/git-subtree.sh \
/usr/lib/git-core/git-subtree

コメントのrui.araujoに感謝します。

履歴をクリアする

デフォルトでは、gitからファイルを削除しても実際にはgitから削除されるわけではなく、それらがもう存在しないことをコミットするだけです。履歴参照を実際に削除する場合(つまり、パスワードをコミットしている場合)、これを行う必要があります。

git filter-branch --Prune-empty --tree-filter 'rm -rf <name-of-folder>' HEAD

その後、ファイルまたはフォルダーがgit履歴にまったく表示されないことを確認できます

git log -- <name-of-folder> # should show nothing

ただし、削除をgithubに「プッシュ」できませんなど。しようとするとエラーが発生し、git pullを実行する前にgit Pushする必要があります。そして、履歴にすべてを戻すことになります。

したがって、「Origin」から履歴を削除する場合-github、bitbucketなどから履歴を削除することを意味します-レポを削除し、レポの剪定コピーを再プッシュする必要があります。しかし、待ってください-他にもあります! -パスワードやそのようなものを取り除くことに本当に懸念がある場合は、バックアップを削除する必要があります(以下を参照)。

.gitを小さくする

前述の削除履歴コマンドでは、まだ多数のバックアップファイルが残っています。gitは、レポジトリを誤って破壊しないようにするのに非常に親切だからです。最終的には孤立したファイルが数日から数か月にわたって削除されますが、誤って不要なものを削除したことに気付いた場合は、しばらくそこに残ります。

ゴミ箱を空にして/をレポジトリのクローンサイズを減らすにしたい場合は、この本当に奇妙なことをすべてしなければなりません:

rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --Prune=now

git reflog expire --all --expire-unreachable=0
git repack -A -d
git Prune

ただし、必要なことがわかっていない限り、これらの手順を実行しないことをお勧めします-間違ったサブディレクトリをプルーニングした場合に備えて、わかりましたか?レポジトリをプッシュしても、バックアップファイルは複製されません。ローカルコピーにあります。

クレジット

1237
CoolAJ86

Paul's answer / ABCを含む新しいリポジトリを作成しますが、/ XYZ内から/ ABCを削除しません。次のコマンドは、/ XYZ内から/ ABCを削除します。

git filter-branch --tree-filter "rm -rf ABC" --Prune-empty HEAD

もちろん、最初に 'clone --no-hardlinks'リポジトリでテストしてから、Paulがリストしているreset、gc、およびPruneコマンドを実行してください。

131
pgs

新しいリポジトリから古い履歴を正しく削除するには、filter-branchステップの後にもう少し作業をしなければならないことがわかりました。

  1. クローンとフィルタを行います。

    git clone --no-hardlinks foo bar; cd bar
    git filter-branch --subdirectory-filter subdir/you/want
    
  2. 古い歴史への言及をすべて削除してください。 “ Origin”はあなたのクローンを追跡し、“ original”はfilter-branchが古いものを保存する場所です。

    git remote rm Origin
    git update-ref -d refs/original/refs/heads/master
    git reflog expire --expire=now --all
    
  3. 今でも、あなたの歴史は、fsckが触れていないpackfileに詰まっているかもしれません。それを細断して新しいパックファイルを作成し、未使用のオブジェクトを削除します。

    git repack -ad
    

filter-branchのマニュアル には これの説明 があります。

94
Josh Lee

編集:bashスクリプトが追加されました。

ここで与えられた答えは私のために部分的に働いただけです。たくさんの大きなファイルがキャッシュに残っていました。最後にうまくいった(freenodeの#gitで数時間後):

git clone --no-hardlinks file:///SOURCE /tmp/blubb
cd blubb
git filter-branch --subdirectory-filter ./PATH_TO_EXTRACT  --Prune-empty --tag-name-filter cat -- --all
git clone file:///tmp/blubb/ /tmp/blooh
cd /tmp/blooh
git reflog expire --expire=now --all
git repack -ad
git gc --Prune=now

以前のソリューションでは、リポジトリサイズは約100 MBでした。これは1.7 MBにそれをもたらしました。多分それは誰かに役立ちます:)


次のbashスクリプトはタスクを自動化します。

!/bin/bash

if (( $# < 3 ))
then
    echo "Usage:   $0 </path/to/repo/> <directory/to/extract/> <newName>"
    echo
    echo "Example: $0 /Projects/42.git first/answer/ firstAnswer"
    exit 1
fi


clone=/tmp/${3}Clone
newN=/tmp/${3}

git clone --no-hardlinks file://$1 ${clone}
cd ${clone}

git filter-branch --subdirectory-filter $2  --Prune-empty --tag-name-filter cat -- --all

git clone file://${clone} ${newN}
cd ${newN}

git reflog expire --expire=now --all
git repack -ad
git gc --Prune=now
39

これはそれほど複雑ではなくなりました。あなたのクローンに対して git filter-branch コマンドを使用して不要なサブディレクトリを選択してから、新しいリモートにプッシュするだけです。

git filter-branch --Prune-empty --subdirectory-filter <YOUR_SUBDIR_TO_KEEP> master
git Push <MY_NEW_REMOTE_URL> -f .
23
jeremyjjbrown

CoolAJ86"The Easy Way™"の答え を少し分割して、複数のサブフォルダ(たとえば、sub1and sub2)を新しいgitリポジトリに追加します。

Easy Way™(複数のサブフォルダー)

  1. 古いレポを準備する

    pushd <big-repo>
    git filter-branch --tree-filter "mkdir <name-of-folder>; mv <sub1> <sub2> <name-of-folder>/" HEAD
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    popd
    

    注:<name-of-folder>には、先頭または末尾の文字を含めることはできません。たとえば、subprojectという名前のフォルダーは、./subproject/ではなく、subprojectとして渡す必要があります

    Windowsユーザーへの注意:フォルダーの深さが1より大きい場合、<name-of-folder>には* nixスタイルのフォルダー区切り文字(/)が必要です。たとえば、path1\path2\subprojectという名前のフォルダーは、path1/path2/subprojectとして渡す必要があります。さらに、mvcommandではなくmoveを使用しないでください。

    最終ノート:基本的な回答とのユニークで大きな違いは、スクリプト「git filter-branch...」の2行目です。

  2. 新しいレポを作成する

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. 新しいリポジトリをGithubまたはどこにでもリンクします

    git remote add Origin <[email protected]:my-user/new-repo.git>
    git Push Origin -u master
    
  4. クリーンアップ、必要に応じて

    popd # get out of <new-repo>
    pushd <big-repo>
    
    git rm -rf <name-of-folder>
    

    :これにより、リポジトリにすべての履歴参照が残ります。パスワードをコミットしたことを実際に懸念する場合、またはパスワードを減らす必要がある場合は、元の回答の付録.gitフォルダーのファイルサイズ。

19
Anthony O.

更新 :git-subtreeモジュールはとても便利だったので、gitチームはそれをコアに組み込んでgit subtreeにしました。こちらを参照してください。 サブディレクトリを別のGitリポジトリに移動(移動)します

git-subtreeはこれに役立ちます

http://github.com/apenwarr/git-subtree/blob/master/git-subtree.txt (廃止予定)

http://psionides.jogger.pl/2010/02/04/sharing-code-between-projects-with-git-subtree/ /

19
D W

元の質問では、XYZ/ABC /(* files)をABC/ABC /(* files)にしたいと考えていました。私自身のコードに対して受け入れられた答えを実装した後、私はそれが実際にXYZ/ABC /(* files)をABC /(* files)に変更することに気づきました。 filter-branchのマニュアルページにも、

結果はそのディレクトリ(そしてそれだけ) をそのプロジェクトのルート とするでしょう。 "

つまり、最上位フォルダを1つ上のレベルに昇格させます。これは重要な違いです。たとえば、私の歴史ではトップレベルのフォルダに名前を変更しました。フォルダを1つ上のレベルに昇格させると、gitは名前を変更したコミットの継続性を失います。

I lost contiuity after filter-branch

質問への私の答えはそれからリポジトリの2つのコピーを作成し、手動であなたがそれぞれに保存したいフォルダを削除することです。 manページはこれで私をバックアップします:

[...]問題を解決するために単純な単一のコミットで十分な場合は[このコマンド]の使用を避けます

11
MM.

Paulの答え に追加するには、最終的にスペースを回復するには、HEADをクリーンなリポジトリにプッシュし、.git/objects/packディレクトリのサイズを小さくする必要があります。 。

すなわち.

 $ mkdir ... ABC.git 
 $ cd ... ABC.git 
 $ git init --bare 

Gc Pruneの後に、以下も行います。

 $ gitプッシュ... ABC.git HEAD 

それからあなたはできる

 $ gitクローン... ABC.git 

そしてABC/.gitのサイズは小さくなります

実際、Push to cleanリポジトリでは、時間のかかる手順(git gcなど)の一部は不要です。

 $ gitクローン - ハードリンクなし/ XYZ/ABC
$ gitフィルタブランチ - サブディレクトリフィルタABC HEAD 
 $ git reset --hard 
 $ gitプッシュ... ABC.git HEAD 
7
Case Larsen

正しい方法は、次のとおりです。

git filter-branch --Prune-empty --subdirectory-filter FOLDER_NAME [first_branch] [another_branch]

GitHubは今や 小物 /そのような場合について/を持っています。

ただし、元のリポジトリを必ず別のディレクトリに複製してください(すべてのファイルと他のディレクトリが削除され、それらを使用する必要がある可能性があるため)。

だからあなたのアルゴリズムは以下のようになるはずです。

  1. リモートレポジトリを別のディレクトリに複製します。
  2. git filter-branchを使用して、いくつかのサブディレクトリの下のファイルだけを残して、新しいリモートにプッシュします
  3. 元のリモートリポジトリからこのサブディレクトリを削除するためのcommitを作成します。
6

ここでの答えの大部分(すべて?)は、何らかの形のgit filter-branch --subdirectory-filterとその同類のものに依存しているようです。ただし、これは「ほとんどの場合」機能する場合があります。たとえば、フォルダの名前を変更した場合などです。

 ABC/
    /move_this_dir # did some work here, then renamed it to

ABC/
    /move_this_dir_renamed

"move_me_renamed"を抽出するために通常のgitフィルタスタイルを実行すると、最初のmove_this_dir( ref )のときに発生したファイル変更履歴が失われます。

したがって、 all 変更履歴を実際に保持する唯一の方法(あなたのものがこのような場合)は、本質的にリポジトリをコピーすること(新しいリポジトリを作成し、Originになるように設定すること)です次に、他のすべてのものを無効にして、サブディレクトリの名前を次のように親に変更します。

  1. マルチモジュールプロジェクトをローカルに複製する
  2. 枝 - そこにあるものをチェックする:git branch -a
  3. ワークステーション上でローカルコピーを取得するために分割に含まれるように各ブランチにチェックアウトを行います。git checkout --track Origin/branchABC
  4. 新しいディレクトリにコピーを作成します。cp -r oldmultimod simple
  5. 新しいプロジェクトのコピーに進みます。cd simple
  6. このプロジェクトで必要とされていない他のモジュールを取り除きます。
  7. git rm otherModule1 other2 other3
  8. ターゲットモジュールのサブディレクトリだけが残る
  9. モジュールのルートが新しいプロジェクトのルートになるように、モジュールのsubdirを削除します。
  10. git mv moduleSubdir1/* .
  11. Relicサブディレクトリを削除します。rmdir moduleSubdir1
  12. いつでも変更を確認してください:git status
  13. 新しいgitリポジトリを作成し、そのURLをコピーしてこのプロジェクトを参照します。
  14. git remote set-url Origin http://mygithost:8080/git/our-splitted-module-repo
  15. これが正しいことを確認します。git remote -v
  16. 変更をリモートリポジトリにプッシュします。git Push
  17. リモートレポジトリに行き、それがすべてそこにあることを確認してください
  18. 他に必要なブランチがあればそれを繰り返します。git checkout branch2

これは githubのドキュメント "サブフォルダを新しいリポジトリに分割する" ステップ6から11へ続きますモジュールを新しいリポジトリにプッシュします。

これはあなたの.gitフォルダ内のスペースを節約することはありませんが、名前を変えてもそれらのファイルのためのあなたのすべての変更履歴を保存します。そして、たくさんの歴史が失われていなければ、これは価値がないかもしれません、など。しかし、少なくともあなたは古いコミットを失わないことが保証されています!

5
rogerdpack

私はまさにこの問題を抱えていましたが、git filter-branchに基づくすべての標準的な解決策は非常に遅いものでした。あなたが小さなリポジトリを持っているなら、これは問題にならないかもしれません、それは私のためでした。私はlibgit2をベースにした別のgitフィルタリングプログラムを書きました。このプログラムは最初のステップとしてプライマリリポジトリのフィルタリングごとにブランチを作成し、次のステップとしてこれらをクリーンリポジトリにプッシュします。私のリポジトリ(500Mb 100000コミット)では、標準のgit filter-branchメソッドは何日もかかりました。私のプログラムは同じフィルタリングをするのに数分かかります。

これはgit_filterという素晴らしい名前を持ち、ここに住んでいます。

https://github.com/slobobaby/git_filter

gitHubで.

私はそれが誰かに役立つことを願っています。

4
slobobaby

その価値があるのは、WindowsマシンでGitHubを使用する方法です。 C:\dir1に常駐するクローンレポジトリがあるとしましょう。ディレクトリ構造はC:\dir1\dir2\dir3のようになります。 dir3ディレクトリは、私が新しく独立したリポジトリにしたいディレクトリです。

Github:

  1. 新しいリポジトリを作成します。MyTeam/mynewrepo

バッシュプロンプト:

  1. $ cd c:/Dir1
  2. $ git filter-branch --Prune-empty --subdirectory-filter dir2/dir3 HEAD
    返される値:Ref 'refs/heads/master' was rewritten(fyi:dir2/dir3は大文字と小文字を区別します。)

  3. $ git remote add some_name [email protected]:MyTeam/mynewrepo.git
    git remote add Origin etc。動作しませんでした。 "remote Origin already exists"を返しました

  4. $ git Push --progress some_name master

4
James Lawruk

より簡単な方法

  1. インストール git splitsjkeating's solution に基づいてgit拡張として作成しました。
  2. ディレクトリをローカルブランチ#change into your repo's directory cd /path/to/repo #checkout the branch git checkout XYZ
    #split multiple directories into new branch XYZ git splits -b XYZ XY1 XY2
    に分割します

  3. 空のリポジトリをどこかに作成します。パスを持つ[email protected]:simpliwp/xyz.gitを持つGitHubにxyzという空のリポジトリを作成したと仮定します。

  4. 新しいレポジトリにプッシュします。 #add a new remote Origin for the empty repo so we can Push to the empty repo on GitHub git remote add Origin_xyz [email protected]:simpliwp/xyz.git #Push the branch to the empty repo's master branch git Push Origin_xyz XYZ:master

  5. 新しく作成したリモートリポジトリを新しいローカルディレクトリに複製します。
    #change current directory out of the old repo cd /path/to/where/you/want/the/new/local/repo #clone the remote repo you just pushed to git clone [email protected]:simpliwp/xyz.git

3
AndrewD

タグとブランチを保持したまま、このfilterコマンドを使用してサブディレクトリを削除します。

git filter-branch --index-filter \
"git rm -r -f --cached --ignore-unmatch DIR" --Prune-empty \
--tag-name-filter cat -- --all
3
cmcginty

サブフォルダを新しいリポジトリに分割するためのGitHubのガイド 。その手順は Paulの答え に似ていますが、私は彼らの指示を理解しやすいと思いました。

GitHubでホストされているものではなく、ローカルリポジトリに適用するように指示を修正しました。


サブフォルダを新しいリポジトリに分割する

  1. Git Bashを開きます。

  2. 現在の作業ディレクトリを、新しいリポジトリを作成したい場所に変更します。

  3. サブフォルダーを含むリポジトリーを複製します。

git clone OLD-REPOSITORY-FOLDER NEW-REPOSITORY-FOLDER
  1. 現在の作業ディレクトリをクローンリポジトリに変更します。
cd REPOSITORY-NAME
  1. リポジトリ内の残りのファイルからサブフォルダを除外するには、次の情報を指定してgit filter-branchを実行します。
    • FOLDER-NAME:あなたのプロジェクト内であなたがから別のリポジトリを作成したいフォルダ。
      • ヒント:Windowsユーザーは、フォルダーを区切るために/を使用する必要があります。
    • BRANCH-NAME:現在のプロジェクトのデフォルトのブランチ。例えばmastergh-pages
git filter-branch --Prune-empty --subdirectory-filter FOLDER-NAME  BRANCH-NAME 
# Filter the specified branch in your directory and remove empty commits
Rewrite 48dc599c80e20527ed902928085e7861e6b3cbe6 (89/89)
Ref 'refs/heads/BRANCH-NAME' was rewritten

私が - 上記で述べたように 、私は(望み通りに)コミットの約95%を削除することでうまくいくように思われる逆の解決策(私のdir/subdir/targetdirに触れないですべてのコミットを削除する)を使わなければなりませんでした。しかし、2つの小さな問題が残っています。

_ first _ filter-branchはコードを導入または変更するコミットを削除するという大きな仕事をしましたが、どうやら マージコミット はGitiverseのそのステーションの下にあります。

これは表面的な問題で、私はおそらくと一緒に暮らすことができるでしょう(彼は言う...目を避けてゆっくりと後退する)

_ 2番目の_ 残っているいくつかのコミットはほとんどありません _ all _ 重複!私は、プロジェクトの歴史全体についての、冗長な第2のタイムラインを取得したようです。興味深いことに(下の写真からわかるように)、私の3つのローカルブランチがすべて同じタイムライン上にあるわけではありません(つまり、それが存在し、単なるガベージコレクションではない理由です)。

私が想像できる唯一のことは、削除されたコミットの1つが、おそらくfilter-branchが実際にdeleteを実行し、コミットされていない各ストランドが独自のコミットのコピーを取ったときに並列タイムラインを作成したシングルマージコミットでした。 。 (shrug私のTARDiSはどこにありますか?)この問題を解決できると確信していますが、本当に何が起こったのかを理解したいと思います。

クレイジーなmergefest-O-RAMAの場合、コミット履歴にそれ自体がしっかりと定着しているので、その1つだけを残すことになるでしょう。外観上の問題がない、そしてそれはTower.appでかなりきれいだから。

3
Jay Allen

https://github.com/vangorra/git_split にあるgit_splitプロジェクトをチェックしてください。

Gitディレクトリを自分のいる場所にある自分自身のリポジトリに変えます。サブツリー面白いビジネスはありません。このスクリプトはあなたのgitリポジトリにある既存のディレクトリを取り、そのディレクトリをそれ自身の独立したリポジトリに変えます。その過程で、あなたが提供したディレクトリの変更履歴全体をコピーします。

./git_split.sh <src_repo> <src_branch> <relative_dir_path> <dest_repo>
        src_repo  - The source repo to pull from.
        src_branch - The branch of the source repo to pull from. (usually master)
        relative_dir_path   - Relative path of the directory in the source repo to split.
        dest_repo - The repo to Push to.
2
vangorra

これをあなたのgitconfigに入れてください。

reduce-to-subfolder = !sh -c 'git filter-branch --tag-name-filter cat --Prune-empty --subdirectory-filter cookbooks/Unicorn HEAD && git reset --hard && git for-each-ref refs/original/ | cut -f 2 | xargs -n 1 git update-ref -d && git reflog expire --expire=now --all && git gc --aggressive --Prune=now && git remote rm Origin'
1
grosser

Gitサブツリーはすべて素晴らしく素晴らしいものですが、移動したいgit管理コードのサブディレクトリはすべてEclipseにありました。あなたがegitを使っているのであれば、それは痛いほど簡単です。移動したいプロジェクトを選択し、チーム - >切断してから、チーム - >新しい場所に共有します。デフォルトでは古いリポジトリの場所を使用しようとしますが、既存の選択をオフにして新しい場所を選択すると移動できます。すべてのあられ。

1
stu

あなたは簡単に https://help.github.com/enterprise/2.15/user/articles/splitting-a-subfolder-out-into-a-new-repository/を試すことができます

これは私のために働きました。上記の手順で直面した問題は

  1. このコマンドではgit filter-branch --Prune-empty --subdirectory-filter FOLDER-NAME BRANCH-NAMEBRANCH-NAMEです master

  2. 保護の問題が原因でコミットしたときに最後の手順が失敗した場合 - https://docs.gitlab.com/ee/user/project/protected_branches.html

0

私は非常に簡単な解決策を見つけました。アイデアはリポジトリをコピーしてから不要な部分を削除することです。これはどのように機能するのかです。

1)分割したいリポジトリを複製する

git clone [email protected]:testrepo/test.git

2)gitフォルダに移動します

cd test/

2)不要なフォルダを削除してコミットする

rm -r ABC/
git add .
enter code here
git commit -m 'Remove ABC'

3) _ bfg _ で不要なフォルダのフォーム履歴を削除する

cd ..
Java -jar bfg.jar --delete-folders "{ABC}" test
cd test/
git reflog expire --expire=now --all && git gc --Prune=now --aggressive

複数のフォルダにはカンマを使用できます

Java -jar bfg.jar --delete-folders "{ABC1,ABC2}" metric.git

4)削除したばかりのファイル/フォルダが履歴に含まれていないことを確認します

git log --diff-filter=D --summary | grep delete

5)ABCを使わずにクリーンなリポジトリを作成したので、新しいOriginにプッシュするだけです。

remote add Origin [email protected]:username/new_repo
git Push -u Origin master

それでおしまい。別のリポジトリを入手するには、この手順を繰り返します。

ステップ3でXY1、XY2を削除し、XYZ - > ABCの名前を変更するだけです。

0