ファイルのチェックアウトなしでGitブランチを切り替える


100

Gitですべてのファイルをチェックアウトせずに別のブランチに切り替えることはできますか?

ブランチを切り替えた後、すべてのファイルを削除して再生成し、コミットして元に戻す必要があります。したがって、ファイルのチェックアウトは時間の無駄です(そして、約14,000のファイルがあり、それは長い操作です)。

すべてを明確にするために:

ドキュメントをGitHub にアップロードするには、これらすべてが必要です。

gh-pagesブランチのあるリポジトリがあります。ドキュメントをローカルで再構築するとき、それをリポジトリー・ディレクトリーにコピーし、コミットしてGitHubにプッシュします。しかし、ローカルに2つのドキュメントのコピーがあったため、満足していませんでした。そして、私は空のブランチを作成し、コミットした後、空に切り替えてファイルを削除することにしました。しかし、元に戻すのは時間がかかるので、この質問をしました。

gh-pagesブランチを離れてファイルを削除できることはわかっていますが、汚い作業ツリーは好きではありません。


あなたにとって「長い」とはどのくらいですか?どのプラットフォームに取り組んでいますか?NFSやその他のファイル共有などのネットワークを介して作業していますか?
グレッグヒューギル

この演習の目的は何ですか?2つのブランチがあり、1つは詳細なコミットがあり、2番目は大きな変更(粗い)のみが記録されますか?
JakubNarębski、2009

おそらく、作業コピーの一時的な(または永続的な)クローンを作成する方が安価です。私の関連する回答記事では、これがメインリポジトリのサブディレクトリとしても機能する方法を示しています。
krlmlr 2015

回答:


106

はい、できます。

git symbolic-ref HEAD refs/heads/otherbranch

このブランチでコミットする必要がある場合は、インデックスもリセットする必要があります。そうしないと、最後にチェックアウトされたブランチに基づいて何かをコミットすることになります。

git reset

1
ブランチの代わりにrefを指すには、echo "ebff34ffb665de0694872dceabe0edeaf50ec5a9" > .git/HEAD続けて使用しgit resetます。
2012年

1
HEADファイルへの直接書き込みは信頼性が低くなります。サブディレクトリにいる場合はどうなりますか?デタッチヘッド(直接SHA1にヘッドポインティング)の場合は、これを試してください: git update-ref HEAD refs/heads/otherbranch
アレクサンダー・バード

2
現在のブランチから新しいブランチにチェックアウトする場合、これを行う別の方法は、1。2 git stash. git checkout -b otherBranch3.git stash pop
Winny

@AlexanderBird:git update-refは便利ですが、現在のブランチの先端も移動します。
tomekwi 2016

47

基本的なgitコマンドのみを使用:

この回答はチャールズの回答より少し長くなっていますが、私が理解できる、したがって覚えている基本的なgitコマンドのみで構成されているため、何度も調べ続ける必要がありません。

現在の場所をマークします(必要に応じて最初にコミットします):

git checkout -b temp

作業ディレクトリを変更せずにマーカーを他のブランチにリセット(移動)します。

git reset <branch where you want to go>

tempと他のブランチは同じコミットを指し、作業ディレクトリは変更されていません。

git checkout <branch where you want to go>

HEADはすでに同じコミットを指しているため、作業ディレクトリは変更されません

git branch -d temp

これらのコマンドは、グラフィカルクライアントからも簡単に利用できることに注意してください。


7
git reset --soft <branch where you want to go>インデックスの更新は避けたい
JoelFan 2015年

7
gitの配管コマンドを避け、磁器のコマンドを優先するというあなたの戦略に同意します。
user64141

26

v2.24 git switchでは金庫のようなものgit checkoutです。
したがって、私はに以下のエイリアスと名前を変更git hopするために
、「worktreeを変更することなく、枝の上にホップ」

読者のために:

Charles Baileyのソリューションは正しいものだと思いますが、このソリューションでは、ローカルブランチではない何かに切り替えるときに微調整が必​​要です。また、理解しやすい通常のコマンドでそれを行う方法がいくつかあるはずです。これが私が思いついたものです:

git checkout --detach
git reset --soft commitish
git checkout commitish

説明:

  • git checkout --detachgit checkout HEAD^{}現在のブランチを残して「デタッチされたヘッド状態」になるのと同じです。したがって、次の変更はHEADブランチに影響しません。切り離しHEADても、ワークツリーやインデックスには影響しません。
  • git reset --soft commitish次にHEAD、指定されたのSHAに移動しcommitishます。インデックスも更新したい場合は残してくださいが、更新は--softお勧めしません。これもまた、ワークツリーには影響せず、(--soft)インデックスにも影響しません。
  • git checkout commitish次にHEAD、指定されたcommitish(ブランチ)に再度アタッチします。(commitishSHAの場合は何も起こりません。)これも、インデックスやワークツリーには影響しません。

このソリューションはコミットを参照するすべてのものを受け入れるため、これはいくつかのgitエイリアスにとって理想的です。rev-parse以下は、タイプミスが誤って(方法はより複雑になり、エラー回復)取り外したヘッド状態に切り替わらないようにすることを確実にするだけで、テスト、チェーンでは何もブレーク、です。

これは次のgit hop treeishエイリアスにつながります:

git config --global alias.hop '!f() { git rev-parse --verify "$*" && git checkout "HEAD^{}" && git reset --soft "$*" && git checkout "$*"; }; f'

参考までに、私のgitエイリアスのリストでそれを見つけることができます。


$@代わりに使いたくないです$*か?違いは、引用符で囲まれた引数が展開されない$ @であり、内部にスペースがあります。
kyb 2018

1
@kyb 関数トリックは別のSOの答えから盗まれます。そして$@、ここで決定的に意味するものではありません。 $*使用の代わりにされている$1、ようにgit switch -f b同じになるgit switch '-f b'エラーであるべきです。私はいくつかのようなエラー処理を離れて残すことによって、別名短縮することができますこの方法!f() { [ 1 = $# ] || { echo 'WTF!'; return 1; }; ..
ティノ

非常に良い解決策です。特に、リモートブランチに使用できること!
Nils-o-mat

14

1つのリポジトリー、または2つのリポジトリーを持つ2つの作業ディレクトリー(2つの作業領域)を持つより良いソリューションではないでしょうか?

これを手助けするgit-new-workdirツールがcontrib/セクションにあります。


git-new-workdirはgit自身のworktreeコマンドと同じですか?ブランチを別のフォルダーにチェックアウトする場合(リポジトリ全体を複製する必要なし)、ワークツリーを使用します。
リュウ

git-new-worktreeスクリプトの以前からのgit worktreeサブコマンド。回答が書かれたとき、このコマンドは利用できませんでした。たとえば、スクリプトにはsymlinkサポートが必要です。私見ネイティブサポートを使用することをお勧めします。
JakubNarębski2017

8

配管のコマンドを探していると思いますgit read-tree。これによりインデックスが更新されますが、作業ディレクトリ内のファイルは更新されません。たとえば、branchは、読み取るブランチの名前であると仮定します。

git read-treeブランチ

次に、今読んだブランチにコミットする場合は、次のことも行う必要があります。

git symbolic-ref HEAD refs / heads / branch

いいえ、ブランチを切り替える必要があるだけで、他の変更はありません-したがって、symbolic-refで十分です
tig

read-treeエラーが生成されます:まだfatal: Not a valid object name branch何もgit switch branchない場合
Andry

7

HEADファイルを別のブランチ名で上書きできます。

echo "ref:refs / heads / MyOtherBranch"> .git / HEAD


13
それはあなたのためにこれを行うには、シンボリック-REFコマンドを使用することをお勧めおそらくです:git symbolic-ref HEAD refs/heads/MyOtherBranch kernel.org/pub/software/scm/git/docs/git-symbolic-ref.html
グレッグHewgill

@GregHewgill、これが、HEADをコミットハッシュに移動する唯一の方法です。あなたはそれでそれを行うことができますgit symbolic-refか?
tomekwi 2016

0

ファイルが非常に多い場合は、ブランチごとに1つずつ、2つのリポジトリを保持するのが最善の方法です。必要に応じて、変更を前後にプルできます。これはgitで壊血病のトリックをプレイするよりも驚くべきことではありません。


あなたは使用することができますgit-new-worktree(ではなく、そのためにcontrib/
ヤクブNarębski

私はよく似たようなことをしました。これは、「怖いgitのもの」を初心者として実行する前にローカルディレクトリをコピーすることです(ブランチの変更など)。皆さんがgit-fuに自信を感じるまでそのルートに行くことをお勧めしますが、可能であればそこから離れることをお勧めします。2つの異なるリポジトリを保持することは問題ありませんが、複雑なレイヤーが追加され、gitの多くの便利な機能(マージ、チェリーピッキングなど)を利用できません。
デビッド

0

リモートブランチが指す場所を変更するだけの場合は、ローカルコピーを変更せずに「git push」で変更できます。

http://kernel.org/pub/software/scm/git/docs/git-push.html

<refspec>パラメータの形式は、オプションのプラス+、ソース参照<src>、コロン:、その後に宛先参照<dst>です。これは、リモートリポジトリ内の<dst>参照を更新する<src>オブジェクトを指定するために使用されます。

たとえば、fooを更新してc5f7ebaをコミットするには、次のようにします。

git push origin c5f7eba:foo

それがあなたが求めていたものかどうかはわかりません。


:質問にはすでに答えましstackoverflow.com/questions/1282639/...を
TIG

0

あなたは利用することができます

      1. git checkout -f <new-branch>
      2. git cherry-pick -x <previous-branch-commit-id>

previous-branch-commit-idは、古いデータをコピーする場所からのコミットです。


-1

ブランチAになりたいが、ブランチBのファイルを使用するとします

gitログを使用してブランチAの現在のコミット参照を見つけます(例: "99ce9a2")。

git checkout A
git reset --hard B
git reset 99ce9a2

これでブランチAになり、Bに対応するフォルダー構造がステージングされていない変更として表示されます(履歴は変更されていません)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.