git-worktreeは何に使用しますか?


210

git-worktreeに関するGithubの投稿を読みました。あの人たちは書く:

featureユーザーがで緊急のバグを報告したときに、というブランチのGitリポジトリで作業しているとしますmaster。最初に、新しいブランチを持つリンクされた作業ツリーを作成し、hotfixマスターに対してチェックアウトします[…]バグを修正し、ホットフィックスをプッシュし、プルリクエストを作成できます。

featureと呼ばれるブランチで作業していて、masterにいくつかの緊急性の高いバグが報告されている場合、私は通常、作業しているものをすべて隠して新しいブランチを作成します。完了したら、作業を続けることができます。これは非常にシンプルなモデルで、私は何年もそのように働いてきました。

一方、git-worktreeの使用には独自の制限があります。

たとえば、2つのリンクされた作業ツリーで同じブランチを同時にチェックアウトすることはできません。これにより、1つの作業ツリーでコミットされた変更により、もう1つが同期しなくなる可能性があります。

既に解決済みの問題に対して、より複雑なワークフローを選択するのはなぜですか?

git-worktree事前に行うことができず、このまったく新しい複雑な機能を正当化することについて何かありますか?


12
隠しておくことができないことの1つは、競合があるマージまたはリベース後のマージされていないパスです。
chirlu

11
コンパイルされた言語で作業する場合、スタッシュとは、スタッシュを解除するときにすべてを再コンパイルする必要があることを意味します。
mb14

同じ(300 MB)ソースコードに基づく複数の異なる製品があり、それらをすべて1つの大きなリポジトリに結合し、ワークツリーを使用して各製品を別のフォルダーにチェックアウトしたままにするのではなく、膨大な数の製品を用意することを計画しています同期しないクローン
エンドリス

回答:


195

私にとって、git worktreeは、久しぶりの改善です。私はエンタープライズソフトウェア開発に携わっています。そこで、3年前にリリースしたような古いバージョンを維持しなければならないことは非常に一般的です。もちろん、バージョンごとにブランチがあるので、バージョンに簡単に切り替えてバグを修正できます。ただし、その間にリポジトリを完全に再構築し、システムを構築する可能性があるため、切り替えにはコストがかかります。切り替えると、IDEはプロジェクト設定を適合させようとして狂ったように動作します。

ワークツリーを使用すると、そのような継続的な再構成を回避できます。ワークツリーを使用して、これらの古いブランチを別のフォルダーにチェックアウトします。ブランチごとに、独立したIDEプロジェクトを取得しました。

もちろん、これは過去にリポジトリを数回複製することで可能でしたが、これまでのところ、これが私のアプローチでした。ただし、これはハードドライブのスペースを浪費し、同じ変更をリポジトリから数回フェッチする必要があることを意味します。


4
リポジトリから同じ変更を何度もフェッチする必要はありませんでした。最初のクローンの.gitディレクトリをコピーするだけで済みます。
misiu_mp 2017年

1
@ JDK1.0申し訳ありませんが、混乱のため、コメントはmisiu_mpに向けた
mxttie

2
2つの高度に複製されたリポジトリを使用して別の機能の開発中に1つの機能ブランチを構築できる誰かとして、各ローカルリポジトリを他のリモートとして使用し、セビの欠点の特徴(大量のフェッチとプッシュ!)に完全に同意します。 )また、ワークツリーに切り替えると、ローカルの同じ名前の分岐が分岐することを心配する必要がなくなることがわかります(これは、6〜10か月に1回程度発生します。複数のリポジトリから同じ機能ブランチを操作するが、それらを再度同期することを忘れる...)
セージ2017

3
@iheanyi —(1)。IDEが特定のディレクトリに関連付けられた外部データファイル(インデックスデータベースなど)を保持している場合は、より高速です。同じディレクトリのコンテンツをスラッシュすると、通常はIDEデータキャッシュが無効になり、インデックスを再作成する必要があります。
Steve Hollasch

5
@iheanyi —(2)時間の経過とともに、すべての履歴は任意の時点で作業ツリーファイルよりもはるかに大きくなります。すべての履歴== .gitディレクトリ。アップストリームからの多くのローカルクローンでは、各クローンが独自の.gitデータベースを持っているため、同じデータベースのローカルコピーが多数あります。多くのローカル作業ツリーでは、各ツリーが同じ.gitデータベースを使用します。はい、ローカルワークツリーのローカルクローンがある場合、Gitは多くの.gitコンテンツをハードリンクしますが、Windowsではハードリンクしません。
Steve Hollasch

70

これにはいくつかの用途があります。

長時間実行するテストスイートがある場合は、何時間も想像してみてください。テストスイートを開始すると、テストが完了するまで作業コピーがブロックされます。これらのテスト中にブランチを切り替えると、理解しにくい方法でブランチが壊れます。

そこで、git-worktree別のブランチがそこで作業するための2番目のアイデアを立ち上げることができます。

また、他のブランチに切り替えて簡単な調査を行うと、IDEは多くのファイルが突然変更されたと見なし、それらのすべての変更にインデックスを付けます。元に戻すときに再度インデックスを付け直す必要があるだけです。

3番目の使用例は、2つのブランチの場合、代わりに2つのディレクトリ間でgit-diff、通常のような他のツールを使用してファイル比較を行うことですdiff


6
git cloneこれらすべてに対してうまく機能しませんか?
-jthill

12
しかし、リモートから大きなリポジトリをクローンするには、長い時間がかかる可能性があります。複製に数分かかる1つのリポジトリに対して作業しています。あなたはそれでそれを行うことができると思いますgit clone --reference。また、他のすべてのブランチの管理は、作業ディレクトリごとに1回ではなく1回だけ行われます。
Andreas Wederbrand 2015

6
リモートからクローンを作成せず、ローカルからクローンを作成します。ブランチ管理の問題を理解していませんが、明確にできますか?
jthill

14
クローンを使ってみましたが、本当に管理上の問題があります。単一のブランチのセットの代わりに、私は単一のUIですべてを一緒に見ることができないクローンのセットを持っています。変更をチェリーピックする必要がある場合は、フェッチまたはプッシュする必要があります。すべてのアクションにステップが追加されます。すべては実行可能ですが、常にある程度の摩擦があります。
max630

2
また、バックアップの設定に関しては、単一のリポジトリの方がはるかに簡単です。
max630

64

明らかな用途の1つは、異なるバージョンの動作(ソースではなく)を同時に比較することです。たとえば、Webサイトの異なるバージョンやWebページだけです。

これをローカルで試しました。

  • ディレクトリを作成しますpage1

  • 内部にディレクトリsrcgit initそれを作成します。

  • 小さなコンテンツでsrc作成page1.htmlし、コミットします。

  • $ git branch ver0

  • $ git worktree add ../V0 ver0

  • srcマスターに多くのテキストを追加page1.htmlし、それをコミットします。

  • $ git branch sty1

  • ブランチで編集page1.htmlsty1(独特のCSSスタイルを追加)、コミットを追加します。

  • $ git worktree add ../S1 sty1

Webブラウザーを使用して、これらの3つのバージョンを同時に開いて表示できるようになりました。

  • ..\page1\src\page1.html // gitが現在持っているものは何でも

  • ..\page1\V0\page1.html //初期バージョン

  • ..\page1\S1\page1.html //実験的なスタイルのバージョン


2
これがクローンよりもこの目的でワークツリーを使用する利点をどのように説明するのかわかりません。
iheanyi 2018年

@iheanyiについても同じことが言えbranchます。答えも同じです。軽量で、仕事用に設計されています。
OJFord

1
@OJFordはちょっとポイントです。この回答では、worktreeが何を行うのかという違いは説明されていません。これは明らかにブランチやクローンのエイリアスではありませんが、ここで見た効果は同じようです。これがブランチやクローンを使用するよりも軽いのかわかりません。
iheanyi

@iheanyiブランチを使用する場合とは異なります。ブランチを単独で使用してワークツリーの複数の状態を一度に取得することはできません。また、2番目(..、n番目)のクローンよりも軽量です。私が言ったのは、ブランチについても「クローンを作成して変更を加えるだけではない」ということですが、単一のリポジトリ内の複数のブランチは軽量で、より簡単にその動作を実現する方法です。
OJFord

@OJFordこれでワークツリーとの混乱が解消されるとは思いません。ここで説明するプロセスの最終目標は、3つの異なるバージョンの何かを同時に比較することです。答えに基づいて、なぜ私がいくつかの代替案よりもワークツリーを使用するのか理解できません。答えは、代替案では行われていないワークツリーの役割を説明していません。あなたは何かが軽量(または軽量)であると主張しますが、ワークツリーがどのようにしてブランチの「重さ」を少なくするかはわかりません。
iheanyi

29
  1. ファイルシステム内の複数のワークツリーを一度に必要とする正当な理由があります。

    • 他の場所で変更を加える必要があるときにチェックアウトされたファイル操作する(例:コンパイル/テスト)

    • 通常のdiffツールでファイルを比較する

    • マージの競合中、ファイルの競合解決しながらソース側にあるソースコードをナビゲートしたいことがよくあります。

    • 頻繁に切り替える必要がある場合、複数のワークツリーを使用する必要がないため、チェックアウトと再チェックアウトの時間が無駄になります。

    • git stashingによるブランチ間のメンタルコンテキストの切り替えによるメンタルコストは、実際には測定できません。一部の人々は、別のディレクトリからファイルを開くだけでは、隠しておくのに精神的なコストがあることに気づきます。

  2. 一部の人々は「なぜ複数のローカルクローンをしないのか」と尋ねます。「--local」フラグを使用すると、余分なディスク領域の使用について心配する必要がないことは事実です。これ(または同様のアイデア)は、私がここまでやってきたことです。ローカルクローンよりもリンクされたワークツリーの機能上の利点は次のとおりです。

    1. ローカルクローンを使用すると、追加のワークツリー(ローカルクローン内にある)は、元のブランチや上流のブランチにアクセスできなくなります。クローンの「起源」は、最初のクローンの「起源」と同じではありません。

      • 実行中git log @{u}..またはgit diff origin/feature/other-feature非常に役立つことができ、これらはもう不可能または困難です。これらのアイデアは、さまざまなワークアロウンを介してローカルクローンで技術的に可能ですが、実行可能なすべての回避策は、リンクされたワークツリーを使用することで、より簡単に、または簡単に実行できます。
    2. ワークツリー間で参照を共有できます。別のローカルブランチからの変更を比較または借用したい場合は、今できます。


11
また、1つのコマンドですべてのワークツリーを一覧表示することもできます。クローンを使用して、自分で追跡する必要があります。
Ian Ringrose 2016年

うーん。git 2.7.0以降ではそうです。知っておくといい。
Alexander Bird

9

tl; dr:何らかの理由で2つの作業ツリーを同時にチェックアウトしたい場合はいつでもgit-worktree、すばやく効率的にスペースを確保できます。

別のワークツリーを作成すると、リポジトリのほとんどの部分(つまり.git)が共有されます。つまり、1つのワークツリーでブランチを作成したりデータをフェッチしたりすると、他のワークツリーからもアクセスできるようになります。ブランチfooでテストスイートを実行して、クローンを作成するためにどこかにプッシュする必要がなく、ローカルでリポジトリのクローンを作成する煩わしさを避けたい場合、を使用git-worktreeして、一時的または永続的に別の場所。クローンの場合と同じように、クローンを使い終わったときに実行する必要があるのは、それを削除することだけです。それに対する参照は、しばらくするとガベージコレクションされます。


2
ドキュメントによると、両方の作業コピーに同じブランチを含めることはできません。これは重大な制限です。Mercurialでは、小さな問題のみで機能しました。
hypersw 2016

できますよ。manページにはその方法が記載されています。を探します--force。しかし、ワークツリーは更新されないため、ブランチを1つの場所で更新し、別の場所でそれを処理することを期待するのは不便です。
jsageryd 2016

そうです、Mercurialのブランチは、この側面ではより透明な概念です。1つのワークツリーからのブランチが他のブランチにどのように表示されますか?複数のアップリンクと同じですか?両方でフェッチを実行して、ワークツリーを使った最初の実験は、という名前の2つの(!)異なる(!)ポインターで終わりましたorigin/master
hypersw 2016

ワークツリーは(名前が示すように)単なるワークツリーであり、いくつかの追加機能が追加されています。リポジトリはすべてのワークツリー間で共有されます。2つのワークツリーの唯一の違いは、チェックアウトされたブランチが異なる可能性があることです(まともなワークフローの場合は異なります)。別のワークツリーでコミットすることは可能であるため、それを機能させるための独自のインデックス(別名ステージング領域)もあります。.git別のワークツリー内のファイルは、元のリポジトリにある構成へのパスを含むテキストファイルです。
jsageryd 2016年

2
@WilsonF:git checkout --ignore-other-worktrees <branch> git-scm.com/docs/git-checkout/...は
jsageryd

7

私はもともと、これらの派手なワークツリーを何に使用できるのか疑問に思って、この質問に出くわしました。それ以来、私はそれらを自分のワークフローに統合し、最初の懐疑論にもかかわらず、それらが非常に有用であることに気付きました。

私はかなり大規模なコードベースで作業しており、コンパイルにはかなり時間がかかります。私は通常、マシンに現在の開発ブランチと、現在取り組んでいる機能ブランチと、ライブシステムの現在の状態を表すマスターブランチがあります。

私にとって最大の利点の1つは、ブランチ(つまり、ワークツリー)を切り替えるたびにすべてを再コンパイルする必要がないことです。良い副作用は、開発ワークツリーに移動し、そこで作業を行い、現在の機能ブランチのディレクトリをワークツリーに変更し、最初にプルする必要なしにリベースできることです。


4

私はかなり珍しいものを持っています:私は同じマシンで WindowsとLinuxの開発をしています。私は自分のWindowsボックス内でLinuxを実行しているVirtualBoxを持っています。VirtualBoxはいくつかのWindowsディレクトリをマウントし、Linuxマシン内で直接使用します。これにより、Windowsを使用してファイルを管理できますが、Linux内でビルドできます。これはクロスプラットフォームプロジェクトであるため、WindowsとLinuxの両方で同じディレクトリ構造から構築されます。

問題は、LinuxとWindowsのビルドシステムが同じディレクトリで使用されると互いにクラッシュすることです。同じディレクトリ名を使用するライブラリなどをダウンロードするためのいくつかの複雑なビルド手順があります。ビルドシステムのWindowsバージョンはWindows固有のライブラリをダウンロードし、ビルドシステムのLinuxバージョンはLinux固有のライブラリをダウンロードします。

理想的な世界では、ビルドシステムはWindowsとLinuxがディレクトリ内で共存できるように変更されますが、現在のところ、問題はワークツリーで対処されています。「Linux」フォルダーはLinux固有のビルドアーティファクトを生成でき、「Windows」フォルダーはWindows固有のビルドアーティファクトを生成できます。これは理想的なソリューションとは言えませんが、ビルドシステムのバグが解決されるのを待つ間、良いギャップを作ります。

確かに、worktreeはこのために設計されていません。私はWindowsバージョンとLinuxバージョンを別々のブランチに保持する必要がありますが、同じブランチに置くことを本当に望んでいます。それでも、それは仕事をしており、ワークツリーがその日を救うという、型破りなケースです。


+1これは、構成ごとのビルド出力ディレクトリをネイティブで行わないようにするための非常に効果的な回避策のようです。UbuntuおよびmacOSゲストで同様のVMware Workstationセットアップを使用しています。
Tanz87 2017年

1

私の新しいプロジェクトでは、機能を作成しました。しかし、いくつかの仕様は失敗しました。結果を比較するためにmasterwork-treeレポを作成しました。何が問題だったか理解するまで、実行コードで結果を段階的に比較しました。


しかし、ワークツリーはこれをクローンよりも簡単にしますか?問題は個人的な好みではなく、具体的な違いです。
IInspectable

1

git worktree機械学習開発に使用しています。

メインの関数コードがあり、異なる実験(異なるアルゴリズムと異なるハイパーパラメーター)の分岐を分割したいと思います。さまざまなアルゴリズムに特化したコードのさまざまなバージョンと一緒にdvcgit worktreeを統合できます。すべてのトレーニングジョブを実行した後、最終的なメトリックを評価し、マージして最適なブランチ/モデルを習得します。

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