gitでは、無関係なブランチをリポジトリに導入する簡単な方法はありますか?


328

今日はgitの問題を抱えている友人を助けている間に、masterブランチから完全に分離する必要があるブランチを紹介する必要がありました。このブランチの内容は、ブランチで開発されたものとは起源が実際には異なりましたが、後でブランチにmasterマージされる予定masterです。

John WiegleyのGitを下から上から読んだとき、ブランチが基本的に特定の規則に従うコミットのラベルであり、コミットがファイルのツリーと、オプションで親コミットにどのように関連付けられているかを思い出しました。gitのplumbを使用して、既存のリポジトリーに親なしのコミットを作成しました。

したがって、インデックス内のすべてのファイルを削除しました...

$ git rm -rf .

... tarballからディレクトリとファイルを抽出し、それらをインデックスに追加しました...

$ git add .

...そしてツリーオブジェクトを作成しました...

$ git write-tree

git-write-tree作成されたツリーオブジェクトのsha1sumを教えてくれました。)

次に、親のコミットを指定せずにツリーをコミットしました...

$ echo "Imported project foo" | git commit-tree $TREE

git-commit-tree作成されたコミットオブジェクトのsha1sumを教えてくれました。)

...そして、新しく作成したコミットを指す新しいブランチを作成しました。

$ git update-ref refs/heads/other-branch $COMMIT

最後に、masterブランチに戻ってそこで作業を続けました。

$ git checkout -f master

これは計画どおりに機能したようです。しかし、これは明らかにgitを使い始めたばかりの人に穏やかに言えば、私がお勧めする種類の手順ではありません。これまでにリポジトリで発生したすべてのこととはまったく無関係の新しいブランチを作成する簡単な方法はありますか?

回答:


510

新しい機能があり(V1.7.2以降)、このタスクを他のどの回答よりも少し高レベルにします。

git checkout--orphanオプションをサポートするようになりました。manページから:

git checkout [-q] [-f] [-m] --orphan <new_branch> [<start_point>]

<new_branch>という名前の新しい孤立したブランチを作成し、<start_point>から開始して、それに切り替えます。この新しいブランチで行われた最初のコミットには親がなく、他のすべてのブランチとコミットから完全に切り離された新しい履歴のルートになります。

これは行いません。まさにそれがインデックスとから作業ツリーを移入するので、アスカーが望んで<start_point>(これがあることから、checkoutコマンドは、すべての後に)。他に必要なアクションは、作業ツリーとインデックスから不要なアイテムを削除することだけです。残念ながらgit reset --hard機能しませんが、git rm -rf .代わりに使用できます(これはrm .git/index; git clean -fdx他の回答で与えられたものと同等であると思います)。


要約すれば:

git checkout --orphan newbranch
git rm -rf .
<do work>
git add your files
git commit -m 'Initial commit'

<start_point>デフォルトはHEADであり、とにかく気にしないので、私は不特定のままにしました。このシーケンスは、基本的にArtemの回答のコマンドシーケンスと同じですが、恐ろしい配管コマンドに頼ることはありません。


他の「ツリー」からブランチをチェックアウトしたときに表示されたままの孤立したブランチを作成できるかどうか知っていますか?
JJD

1
@JJD:git mergeが必要だと思います。 ( git checkout master && git merge --no-commit "orphan-branch" ) 同様のいくつかのトリックは、git-resetを使用するか、インデックスを操作することで機能します。しかし、それはあなたが望むワークフローに依存します。
2010

@Matthewこれがgit 1.7.2の変更ログです
JJD 2011

@phord私は多かれ少なかれ孤児を、プロジェクトのソースコードから分離された単体テストやドキュメントのようなものを含むと考えました。
JJD 2011

2
@JJD:私があなたを誤解しない限り、私が提供したスクリプトはあなたが望むものをあなたに与えるはずです。「表示され続ける」と言ったとき、別のブランチをチェックアウトした場合でも、ファイルが作業ディレクトリに残ることを意味しますか?--no-commiton git mergeを使用すると、これを実現できます。git reset origin/master次のコミットを希望どおりに進めるために、フォローアップが必要になる場合がありますが、.gitignoreファイルに含めない限り、孤立ブランチのファイルは「追跡されていないファイル」として表示されます。
phord

32

Gitコミュニティブックから:

git symbolic-ref HEAD refs/heads/newbranch 
rm .git/index 
git clean -fdx 
<do work> 
git add your files 
git commit -m 'Initial commit'

1
次の答えは、gitの最新バージョンに適しています。
キキト2012

14
@kikito:Re:「次の回答の方がいい」... SOでのここの順序は安定していません。あなたがより良い答えだと思うものを指すリンクを追加できますか?
David J.

2
私はstackoverflow.com/a/4288660/312586を参照していました。あなたは正しい、私は「次へ」と言ってはならない。私がコメントしたとき、それはこの答えよりスコアが少なかった。
キキト2014年


これは、「ブランチにコミットし、それが以前に存在していなかった場合は作成する」場合に
適して

22

git symbolic-refインデックスを使用したソリューションと削除したソリューションは機能しますが、新しいリポジトリを作成する方が概念的にはクリーンな場合があります

$ cd /path/to/unrelated
$ git init
[edit and add files]
$ git add .
$ git commit -m "Initial commit of unrelated"
[master (root-commit) 2a665f6] Initial commit of unrelated
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 foo

それからそれをフェッチします

$ cd /path/to/repo
$ git fetch /path/to/unrelated master:unrelated-branch
warning: no common commits
remote: Counting objects: 3, done.
Unpacking objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
From /path/to/unrelated
 * [new branch]      master     -> unrelated-branch

/ path / to / unrelatedを削除できるようになりました


私の意見では、きれいな概念がするオプションを伴うだろうgit branchgit checkout。gitがこのようなことを可能にしてくれてうれしいのですが、なぜもっと簡単にすべきではないのですか?
hillu 2009

3
ですので、珍しい物になるはずです。無関係なものブランチがある場合、それは通常、既存のものに詰め込むのではなく、無関係なリポジトリに属します(例外はありますが)。
JakubNarębski、2009

1
+1。仲間のgit初心者は、どうやらブランチを一覧表示して、でブランチをgit branch切り替えることができますgit checkout BRANCH_NAME
akavel 2011

このおかげで、私は自分でそれについて考えることはなかったでしょう。これは、他のリポジトリの履歴(存在する場合)を維持するため、非常に役立ちます。
BM5k

13

GithubにProject Pagesと呼ばれる機能があり、プロジェクトに特定の名前付きブランチを作成して、Githubによって提供されるファイルを提供できます。その指示は次のとおりです。

$ cd /path/to/fancypants
$ git symbolic-ref HEAD refs/heads/gh-pages
$ rm .git/index
$ git clean -fdx

そこから、新しいコンテンツを追加できる空のリポジトリがあります。


10

現在選択されている答えは正しいですが、私は偶然それを追加します...

これは実際に、github.comがと呼ばれる孤立したブランチを介して、ユーザーがリポジトリ用のGithubページを作成できるようにする方法ですgh-pages。かなりのステップがここに与えられ、説明されています:

https://help.github.com/articles/creating-project-pages-manually

基本的に、これを設定するgitコマンドは次のとおりです。

  1. git checkout --orphan gh-pages (リポジトリにgh-pagesという親のないブランチを作成します)
  2. git rm -rf . (ブランチ作業ツリーからファイルを削除します)
  3. rm '.gitignore' (gitignoreでも)
  4. 次に、Webサイトのコンテンツを追加し(index.htmlなどを追加)、コミットしてプッシュします。
  5. 利益。

/ docsフォルダを指定することもできますリポジトリのを、GithubがWebサイトの構築に使用する「プロジェクトサイト」のソースとして。

お役に立てれば!


3

プロジェクトに空のブランチをすぐに作成して作業を開始したい場合があります。次のコマンドを実行します。

git checkout --orphan unrelated.branch.name
git rm --cached -r .
echo "init unrelated branch" > README.md
git add README.md
git commit -m "init unrelated branch"

1

既存のコンテンツがすでにコミットされている場合、「Git 2.18 Q2 2018」は、「」の実装以降、独自の孤立したブランチにコンテンツを抽出できます。git rebase -i --rootされている場合、シーケンサーメカニズムをさらに使用するよう」が更新されているます。

そのシーケンサーは、コミットグラフのトポロジ全体を他の場所に移植できるようになりました

Johannes Schindelinによるcommit 8fa6eeacommit 9c85a1ccommit ebddf39commit 21d0764commit d87d48bcommit ba97aea(03 May 2018)を参照してくださいdscho
(による合併Junio C浜野- gitster-c5aa4bcをコミットし、2018年5月30日)

シーケンサー:新しいルートコミットの導入を許可

--rebase-merges既存のブランチトポロジを自由に変更できるように特別に設計された新しいモードのコンテキストでは、新しく作成されたルートコミットで始まる完全に新しいブランチにコミットを抽出することができます。

これは、ルートコミットになりたいコミットを実行するreset [new root]前 にコマンドを挿入することで可能pickになりました。例:

reset [new root]
pick 012345 a commit that is about to become a root commit
pick 234567 this commit will have the previous one as parent

これは、resetコマンドの 他の使用と競合しません。[new root]は有効な参照名(の一部)ではないは参照名では、開始ブラケットとスペースの両方が無効です。


0

このスクリプトはhttp://wingolog.org/archives/2008/10/14/merging-in-unrelated-git-branchesで見つかり、非常にうまく機能します!

#!/bin/bash

set -e

if test -z "$2" -o -n "$3"; then
    echo "usage: $0 REPO BRANCHNAME" >&2
    exit 1
fi

repo=$1
branch=$2

git fetch "$repo" "$branch"

head=$(git rev-parse HEAD)
fetched=$(git rev-parse FETCH_HEAD)
headref=$(git rev-parse --symbolic-full-name HEAD)

git checkout $fetched .

tree=$(git write-tree)

newhead=$(echo "merged in branch '$branch' from $repo" | git commit-tree $tree -p $head -p $fetched)
git update-ref $headref $newhead $head
git reset --hard $headref

1
同じ効果がを使用して達成できると思いますgit fetch $REMOTE $REMOTE_BRANCH:$LOCAL_BRANCH。何か不足していますか?
hillu 2010
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.