どのように輸入、既存のGitリポジトリに入りではありませんか?

StackOverflow https://stackoverflow.com/questions/1683531

  •  18-09-2019
  •  | 
  •  

質問

いGitリポジトリにというフォルダ XXX, で、第二のGitリポジトリと呼ばれ YYY.

たいへの輸入 XXX リポジトリの YYY リポジトリとサブディレクトリ名 ZZZ すべての追加 XXX'"s%s"未登録"s bs"変更履歴 YYY.

フォルダ構成:

XXX
 |- .git
 |- (project files)
YYY
 |- .git
 |- (project files)

フォルダ構造変更後:

YYY
 |- .git  <-- This now contains the change history from XXX
 |-  ZZZ  <-- This was originally XXX
      |- (project files)
 |-  (project files)

で実現できるのやらなければいけませーリゾートをサブモジュール?

役に立ちましたか?

解決

おそらく最も簡単な方法は、それを引くことです xxx の枝に詰め込みます ええ そして、それをマスターにマージします:

ええ:

git remote add other /path/to/XXX
git fetch other
git checkout -b ZZZ other/master
mkdir ZZZ
git mv stuff ZZZ/stuff                      # repeat as necessary for each file/dir
git commit -m "Moved stuff to ZZZ"
git checkout master                
git merge ZZZ --allow-unrelated-histories   # should add ZZZ/ to master
git commit
git remote rm other
git branch -d ZZZ                           # to get rid of the extra branch before pushing
git push                                    # if you have a remote, that is

私は実際に私のリポジトリをいくつか試してみましたが、それは機能します。ようではない ヨルグの答え 他のリポジトリを使用し続けることはできませんが、とにかくそれを指定したとは思いません。

注:これは元々2009年に書かれていたため、Gitは以下の回答に記載されているサブツリーマージを追加しました。もちろん、この方法はまだ機能していますが、今日はその方法を使用するでしょう。

他のヒント

2番目のリポジトリの正確なコミット履歴を保持し、したがって、将来上流の変更を簡単にマージする能力を保持したい場合は、ここに必要な方法があります。その結果、マージされたリポジトリをサブディレクトリに移動するために、サブツリーがリポジトリにインポートされ、1つのマージのコミットメントがインポートされます。

git remote add XXX_remote <path-or-url-to-XXX-repo>
git fetch XXX_remote
git merge -s ours --no-commit --allow-unrelated-histories XXX_remote/master
git read-tree --prefix=ZZZ/ -u XXX_remote/master
git commit -m "Imported XXX as a subtree."

次のように上流の変更を追跡できます。

git pull -s subtree XXX_remote master

gitは、マージを行う前にルーツがある場所で独自に把握しているため、後続のマージでプレフィックスを指定する必要はありません。

2.9以前のgitバージョン: :合格する必要はありません --allow-unrelated-histories のオプション git merge.

使用する他の答えの方法 read-tree そして、スキップします merge -s ours ステップは、事実上、CPを使用してファイルをコピーして結果をコミットすることと違いはありません。

元のソースはからでした Githubの「サブツリーマージ」ヘルプ記事.

git-subtree 履歴を保持しながら複数のリポジトリを1つにマージするこのユースケースのために設計されたスクリプトです(および/またはサブツリーの履歴を分割しますが、これはこの質問とは無関係であるようです)。 Gitツリーの一部として分布しています リリース1.7.11以来.

リポジトリをマージします <repo> 改訂時 <rev> サブディレクトリとして <prefix>, 、 使用する git subtree add 次のように:

git subtree add -P <prefix> <repo> <rev>

git-subtreeは実装します サブツリーマージ戦略 よりユーザーフレンドリーな方法で。

あなたの場合、リポジトリyyy内で、あなたは実行します:

git subtree add -P ZZZ /path/to/XXX.git master

GITリポジトリ自体には、これについてよく知られているインスタンスがあります。これは、GITコミュニティで総称して「」と総称されています。これまでで最もクールなマージ"(件名の後、このマージを説明するgit maelinglistに電子メールで使用されたlinus torvalds。この場合、 gitk 現在、GIT適切なGIT GUIは、実際には別のプロジェクトでした。 Linusは、そのリポジトリをGitリポジトリに統合することができました。

  • Gitリポジトリには、Gitの一部として常に開発されていたかのように表示されます。
  • すべての歴史はそのままにされています
  • それはまだ古いリポジトリで独立して開発することができ、変化は単に git pull

電子メールには、再現するために必要な手順が含まれていますが、それは心のかすかな人のためではありません:最初、Linus 書きました git、だから彼はおそらくあなたや私よりもそれについてもう少し知っているでしょう、そして第二に、これはほぼ5年前であり、gitは改善されました かなり それ以来、多分それは今でははるかに簡単です。

特に、私は最近では、その特定の場合、Gitkサブモジュールを使用すると思います。

それを行う簡単な方法は、gitフォーマットパッチを使用することです。

2つのgitリポジトリがあると仮定します fooバー.

foo 含まれる:

  • foo.txt
  • 。ギット

バー 含まれる:

  • bar.txt
  • 。ギット

そして、私たちは終わらせたいと思っています foo を含む バー 履歴とこれらのファイル:

  • foo.txt
  • 。ギット
  • Foobar/bar.txt

そうするために:

 1. create a temporary directory eg PATH_YOU_WANT/patch-bar
 2. go in bar directory
 3. git format-patch --root HEAD --no-stat -o PATH_YOU_WANT/patch-bar --src-prefix=a/foobar/ --dst-prefix=b/foobar/
 4. go in foo directory
 5. git am PATH_YOU_WANT/patch-bar/*

そして、私たちができるバーからすべてのメッセージコミットを書き直したい場合、例えばLinuxについて:

git filter-branch --msg-filter 'sed "1s/^/\[bar\] /"' COMMIT_SHA1_OF_THE_PARENT_OF_THE_FIRST_BAR_COMMIT..HEAD

これにより、各コミットメッセージの先頭に「[bar]」が追加されます。

ベース この記事で, 、サブツリーを使用することは私のために働いたものであり、適用可能な履歴のみが転送されました。誰かが手順を必要とする場合に備えてここに投稿します(プレースホルダーを必ずあなたに適用される価値に置き換えてください):

ソースリポジトリでサブフォルダーを新しいブランチに分割します

git subtree split --prefix=<source-path-to-merge> -b subtree-split-result

宛先でレポが分割されたブランチにマージされます

git remote add merge-source-repo <path-to-your-source-repository>
git fetch merge-source-repo
git merge -s ours --no-commit merge-source-repo/subtree-split-result
git read-tree --prefix=<destination-path-to-merge-into> -u merge-source-repo/subtree-split-result

変更を確認し、コミットします

git status
git commit

忘れないでください

削除してクリーンアップします subtree-split-result ブランチ

git branch -D subtree-split-result

追加したリモートを削除して、ソースリポジトリからデータを取得します

git remote rm merge-source-repo

この関数は、すべてのコミットをマージした後、リモートリポジトリがローカルリポジトリにクローンされます。 git log 元のコミットと適切なパスが表示されます。

function git-add-repo
{
    repo="$1"
    dir="$(echo "$2" | sed 's/\/$//')"
    path="$(pwd)"

    tmp="$(mktemp -d)"
    remote="$(echo "$tmp" | sed 's/\///g'| sed 's/\./_/g')"

    git clone "$repo" "$tmp"
    cd "$tmp"

    git filter-branch --index-filter '
        git ls-files -s |
        sed "s,\t,&'"$dir"'/," |
        GIT_INDEX_FILE="$GIT_INDEX_FILE.new" git update-index --index-info &&
        mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
    ' HEAD

    cd "$path"
    git remote add -f "$remote" "file://$tmp/.git"
    git pull "$remote/master"
    git merge --allow-unrelated-histories -m "Merge repo $repo into master" --edit "$remote/master"
    git remote remove "$remote"
    rm -rf "$tmp"
}

使い方:

cd current/package
git-add-repo https://github.com/example/example dir/to/save

少し変更を加えると、ファイル/マージされたリポジトリの移動することもできます。たとえば、次のようになります。

repo="https://github.com/example/example"
path="$(pwd)"

tmp="$(mktemp -d)"
remote="$(echo "$tmp" | sed 's/\///g' | sed 's/\./_/g')"

git clone "$repo" "$tmp"
cd "$tmp"

GIT_ADD_STORED=""

function git-mv-store
{
    from="$(echo "$1" | sed 's/\./\\./')"
    to="$(echo "$2" | sed 's/\./\\./')"

    GIT_ADD_STORED+='s,\t'"$from"',\t'"$to"',;'
}

# NOTICE! This paths used for example! Use yours instead!
git-mv-store 'public/index.php' 'public/admin.php'
git-mv-store 'public/data' 'public/x/_data'
git-mv-store 'public/.htaccess' '.htaccess'
git-mv-store 'core/config' 'config/config'
git-mv-store 'core/defines.php' 'defines/defines.php'
git-mv-store 'README.md' 'doc/README.md'
git-mv-store '.gitignore' 'unneeded/.gitignore'

git filter-branch --index-filter '
    git ls-files -s |
    sed "'"$GIT_ADD_STORED"'" |
    GIT_INDEX_FILE="$GIT_INDEX_FILE.new" git update-index --index-info &&
    mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
' HEAD

GIT_ADD_STORED=""

cd "$path"
git remote add -f "$remote" "file://$tmp/.git"
git pull "$remote/master"
git merge --allow-unrelated-histories -m "Merge repo $repo into master" --edit "$remote/master"
git remote remove "$remote"
rm -rf "$tmp"

通知
パスは介して置き換えます sed, 、そのため、マージした後、適切なパスに移動したことを確認してください。
--allow-unrelated-histories パラメーターはgit> = 2.9以降のみ存在します。

これはもう少し簡単だと思うので、別の答えを追加します。 repo_destのプルはrepo_to_importに行われ、次にプッシュ - set-upstream url:repo_destマスターが完了します。

この方法は、いくつかの小さなリポジトリをより大きなものにインポートするために機能しました。

インポートする方法:repo_to_destへのrepo1_to_import

# checkout your repo1_to_import if you don't have it already 
git clone url:repo1_to_import repo1_to_import
cd repo1_to_import

# now. pull all of repo_dest
git pull url:repo_dest
ls 
git status # shows Your branch is ahead of 'origin/master' by xx commits.
# now push to repo_dest
git push --set-upstream url:repo_dest master

# repeat for other repositories you want to import

インポートを行う前に、元のレポでファイルと監督を元のリポジトリに変更または移動します。例えば

cd repo1_to_import
mkdir topDir
git add topDir
git mv this that and the other topDir/
git commit -m"move things into topDir in preparation for exporting into new repo"
# now do the pull and push to import

次のリンクで説明されている方法は、この答えに影響を与えました。もっと簡単に思えたので、私はそれが好きでした。しかし、注意してください!ドラゴンがあります! https://help.github.com/articles/importing-an-external-git-repository git push --mirror url:repo_dest ローカルレポの履歴と状態をリモートにプッシュします(url:repo_dest)。しかし、それはリモートの古い歴史と状態を削除します。楽しみが続く! :-e

私の場合、他のリポジトリ(xxx)からいくつかのファイルのみをインポートしたかったのです。サブツリーは私には複雑すぎて、他のソリューションは機能しませんでした。これが私がしたことです:

ALL_COMMITS=$(git log --reverse --pretty=format:%H -- ZZZ | tr '\n' ' ')

これにより、インポートしたいファイル(ZZZ)に影響を与えるすべてのコミットのスペースが区切られたリストが提供されます(変更を追加する必要がある場合もあります)。その後、ターゲットリポジトリ(YYY)に入り、他のリポジトリ(xxx)をリモートとして追加し、そこからフェッチを行い、最後に次のようにしました。

git cherry-pick $ALL_COMMITS

これにより、ブランチにすべてのコミットが追加されます。したがって、あなたは彼らの歴史を持つすべてのファイルを持っており、彼らが常にこのリポジトリにいるかのように彼らと一緒に好きなことをすることができます。

私は探していた状況にありました -s theirs しかし、もちろん、この戦略は存在しません。私の歴史は、私がgithubでプロジェクトを分岐したということでした、そして今、何らかの理由で、私の地元 master マージすることはできませんでした upstream/master 私はこの支店に局所的な変更を加えていませんでしたが。 (本当にそこで何が起こったのかわからない - 上流は舞台裏でいくつかの汚いプッシュをしたと思う?)

私がやったことはそうでした

# as per https://help.github.com/articles/syncing-a-fork/
git fetch upstream
git checkout master
git merge upstream/master
....
# Lots of conflicts, ended up just abandonging this approach
git reset --hard   # Ditch failed merge
git checkout upstream/master
# Now in detached state
git branch -d master # !
git checkout -b master   # create new master from upstream/master

だから今私 master 再び同期しています upstream/master (そして、同様に同期したい他のブランチについては、上記を繰り返すことができます)。

見る 基本的な例この記事 リポジトリのそのようなマッピングを検討してください。

  • A <-> YYY,
  • B <-> XXX

この章で説明されているすべての活動の後(マージした後)、ブランチを削除します B-master:

$ git branch -d B-master

次に、変更をプッシュします。

わたしにはできる。

別のソリューションを提案できます(代替案 git-submodules)あなたの問題のために - GIL(gitリンク)ツール

複雑なGITリポジトリの依存関係を説明および管理できます。

また、それはのソリューションを提供します GIT再帰サブモジュールの依存関係の問題.

次のプロジェクト依存関係があると考えてください。サンプルGITリポジトリ依存性グラフ

その後、定義できます .gitlinks リポジトリの関係を備えたファイル説明:

# Projects
CppBenchmark CppBenchmark https://github.com/chronoxor/CppBenchmark.git master
CppCommon CppCommon https://github.com/chronoxor/CppCommon.git master
CppLogging CppLogging https://github.com/chronoxor/CppLogging.git master

# Modules
Catch2 modules/Catch2 https://github.com/catchorg/Catch2.git master
cpp-optparse modules/cpp-optparse https://github.com/weisslj/cpp-optparse.git master
fmt modules/fmt https://github.com/fmtlib/fmt.git master
HdrHistogram modules/HdrHistogram https://github.com/HdrHistogram/HdrHistogram_c.git master
zlib modules/zlib https://github.com/madler/zlib.git master

# Scripts
build scripts/build https://github.com/chronoxor/CppBuildScripts.git master
cmake scripts/cmake https://github.com/chronoxor/CppCMakeScripts.git master

各行は、次の形式でgitリンクを説明しています。

  1. リポジトリの一意の名前
  2. リポジトリの相対パス(.gitlinksファイルのパスから開始)
  3. git cloneコマンドリポジトリブランチで使用されるgitリポジトリチェックアウト
  4. #で開始された空の行または行は解析されません(コメントとして扱われます)。

最後に、ルートサンプルリポジトリを更新する必要があります。

# Clone and link all git links dependencies from .gitlinks file
gil clone
gil link

# The same result with a single command
gil update

その結果、必要なすべてのプロジェクトをクローン化し、適切な方法で互いにリンクします。

子どものリンクされたリポジトリのすべての変更を伴うリポジトリですべての変更をコミットしたい場合は、単一のコマンドでそれを行うことができます。

gil commit -a -m "Some big update"

プル、プッシュコマンドも同様の方法で機能します。

gil pull
gil push

GIL(git links)ツールは、次のコマンドをサポートしています。

usage: gil command arguments
Supported commands:
    help - show this help
    context - command will show the current git link context of the current directory
    clone - clone all repositories that are missed in the current context
    link - link all repositories that are missed in the current context
    update - clone and link in a single operation
    pull - pull all repositories in the current directory
    push - push all repositories in the current directory
    commit - commit all repositories in the current directory

もっと GIT再帰サブモジュールの依存関係の問題.

知らない手軽に行うことができます。なにができること:

  1. 利用gitフィルター-支店を追加するZZZスーパー-ディレクトリXXXリポジトリ
  2. を押して新しい支店をYYYリポジトリ
  3. 合併の進支店YYY幹.

できる編集内容が事実に反する場合その音の魅力です。

「Git MV」と「Git Pull」を使用してこれを行うことができると思います。

私は公正なgit noobです - あなたのメインリポジトリに注意してください - しかし、私はこれを一時的な監督で試したばかりで、それはうまくいくようです。

まず - XXXの構造を名前に変更して、Yyy内にあるときに見たい方法と一致させます。

cd XXX
mkdir tmp
git mv ZZZ tmp/ZZZ
git mv tmp ZZZ

今、xxxは次のようになります:

XXX
 |- ZZZ
     |- ZZZ

次に、「git pull」を使用して変更を取得します。

cd ../YYY
git pull ../XXX

今、yyyはこんな感じです:

YYY
 |- ZZZ
     |- ZZZ
 |- (other folders that already were in YYY)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top