513

Git のブランチ、フォーク、クローンの違いを理解したいですか?

git fetch同様に、 aではなくa を実行すると、どういう意味になりgit pullますか?

また、rebaseと比べて とはどういう意味mergeですか?

個々のコミットをまとめてつぶすにはどうすればよいですか?

それらはどのように使用され、なぜ使用され、何を表しているのでしょうか?

GitHub はどのように関与していますか?

4

5 に答える 5

546

ギット

この回答には GitHub も含まれています。

ローカル リポジトリ

Git (ローカル) には、.gitファイルをコミットするディレクトリ ( ) があり、これが「ローカル リポジトリ」です。これは、リモート リポジトリに追加してすぐにコミットする SVN のようなシステムとは異なります。

Git は、ファイル全体を保存することによって変更されるファイルの各バージョンを保存します。デルタ変更によって「再作成」せずに個々のバージョンに移動できるため、この点でも SVN とは異なります。

Git はファイルをまったく「ロック」しないため、編集のための「排他的ロック」機能を回避するため (PVC のような古いシステムが思い浮かびます)、オフラインの場合でもすべてのファイルを常に編集できます。これは、GitHub などのリモート リポジトリへのプルまたはフェッチ/プッシュ中に、ファイルの変更を (同じファイル内で!) マージするという驚くべき仕事を実際に行います。手動で変更 (実際にファイルを編集) する必要があるのは、2 つの変更が同じコード行に関係する場合だけです。


支店

ブランチを使用すると、メイン コード (「マスター」ブランチ) を保存し、コピー (新しいブランチ) を作成してから、その新しいブランチ内で作業できます。作業に時間がかかる場合、またはブランチが作成されてからマスターが多くの更新を取得する場合は、マスター ブランチに対してマージまたはリベース (履歴を改善し、競合を解決しやすくするために好まれることがよくあります) を行う必要があります。完了したら、ブランチで行った変更をマスター リポジトリにマージします。多くの組織は、機能、バグ、雑用項目のいずれであっても、作業ごとにブランチを使用しています。他の組織は、バージョン アップグレードなどの主要な変更の場合にのみブランチを使用します。

フォーク: ブランチでは、ブランチを制御および管理しますが、フォークでは、他の誰かがコードの受け入れを制御します。

大まかに言えば、ブランチを行うには主に 2 つのアプローチがあります。1 つ目は、ほとんどの変更をマスター ブランチに保持することです。ブランチは、異なるニーズに合わせて 2 つのブランチを利用できるようにしたいバージョン変更など、大規模で長時間実行されるものにのみ使用します。2 つ目は、基本的にすべての機能要求、バグ修正、雑用ごとにブランチを作成し、それらのブランチを実際にメインのマスター ブランチにマージするタイミングを手動で決定する方法です。これは退屈に聞こえるかもしれませんが、これは一般的なアプローチであり、私が現在使用および推奨しているアプローチです。これにより、マスター ブランチがクリーンに保たれ、本番環境に昇格するのはマスターであるためです。枝の合併。

master にブランチを「イン」する標準的な方法は、merge. ブランチは、履歴を「クリーンアップ」するために「リベース」することもできます。これは現在の状態には影響せず、「よりクリーンな」履歴を提供するために行われます。

基本的には、特定のポイント (通常はマスター) から分岐するという考え方です。あなたが分岐したので、「マスター」自体はその分岐点から前進しました。ブランチで行ったすべての変更が、最新のすべての変更を含むマスターの現在の状態に対して実行される場合、「よりクリーン」になります (問題の解決が容易になり、履歴が理解しやすくなります)。したがって、プロセスは次のとおりです。変更を保存します。「新しい」マスターを取得し、それに対して変更を再度適用します(これはリベース部分です)。リベースは、マージと同様に、手動で解決する必要がある競合を引き起こす可能性があることに注意してください (つまり、編集と修正)。

注意すべき 1 つのガイドライン:
ブランチがローカルで、まだリモートにプッシュしていない場合にのみリベースしてください。
これは主に、リベースによって他の人が見る履歴が変更され、自分のコミットが含まれる可能性があるためです。

ブランチの追跡

これらは名前が付けられたブランチですorigin/branch_name(単に とは対照的にbranch_name)。リモートリポジトリとの間でコードをプッシュおよびプルする場合、これは実際にそれを行うメカニズムです。たとえばgit push、ブランチという名前building_groupsの場合、ブランチは最初にorigin/building_groupsリモート リポジトリに移動し、次にリモート リポジトリに移動します。同様に、 を実行するgit fetch building_groupsと、取得されたファイルがorigin/building_groupsブランチに配置されます。次に、このブランチをローカル コピーにマージすることを選択できます。私たちの慣行は、 (上記の両方を 1 つのステップで実行する)git fetchだけではなく、常に手動でマージすることです。git pull

新しいブランチを取得しています。

新しいブランチの取得: クローンの最初の時点で、すべてのブランチがあります。ただし、他の開発者がブランチを追加してリモートにプッシュする場合、それらのブランチとその名前を「知る」方法が必要です。これにより、それらをローカルにプルダウンできるようになります。git fetchこれは、追跡ブランチ (例: ) を使用して、すべての新しいブランチと変更されたブランチをローカル リポジトリに取得する を介して行われますorigin/fetch編集するとgit branch --remote、追跡ブランチを一覧表示し、git checkout [branch]実際に任意のブランチに切り替えることができます。

マージ

マージは、異なるブランチまたは同じブランチの異なるバージョンからのコード変更を結合するプロセスです (たとえば、ローカル ブランチとリモートが同期していない場合)。ブランチで作業を開発し、作業が完了し、準備が整い、テストされている場合は、ブランチにマージできますmaster。これは、ブランチgit checkout masterに切り替えてから. マージにより、すべての異なるファイルと、同じファイルへの異なる変更さえもまとめられます。これは、ファイル内のコードを実際に変更して、すべての変更をマージすることを意味します。mastergit merge your_branch

を実行するときcheckoutは、リモート マスターの最新バージョンをローカル マスターにマージするためにmasterを実行することもお勧めします。git pull origin masterリモート マスターが変更された場合、つまり、moved forwardその間にそれを反映する情報が表示されgit pullます。その場合 (マスターが変更された場合) は、変更が実際に「新しい」マスターの上で「再生」されるようにマスターすることをお勧めしgit checkout your_branchます。rebase次に、次の段落に示すように、マスターを最新の状態にします。

競合がない場合、master に新しい変更が追加されます。競合がある場合、これは、同じファイルに、自動的にマージできない類似のコード行に関する変更があることを意味します。この場合git merge new_branch、解決すべき競合があることが報告されます。ファイルを編集し(両方の変更が含まれます)、必要な変更を選択し、不要な変更の行を文字通り削除してからファイルを保存することで、それらを「解決」します。========変更は、やなどの区切り記号でマークされ<<<<<<<<ます。

コンフリクトを解決したら、もう一度git addそれらgit commitの変更を加えてマージを続行します (このプロセス中に git からフィードバックが得られます)。

プロセスがうまくいかない場合、git merge --abort物事をリセットするのに非常に便利です。

インタラクティブなリベースとスカッシュ/並べ替え/コミットの削除

たとえば、コードを毎日「進行中」としてコミットするなど、多くの小さなステップで作業を行った場合、これらの多くの小さなコミットをいくつかの大きなコミットに「押しつぶす」ことができます。これは、同僚とコード レビューを行う場合に特に便利です。(コミットを介して) 行ったすべての「ステップ」を再生したくない場合は、1 つのコミットでのこの作業のすべての変更の最終結果 (差分) がここにあると言いたいだけです。

これを行うかどうかを検討する際に評価する重要な要素は、複数のコミットが同じファイルまたは複数のファイルに対するものであるかどうかです (その場合、コミットをスカッシュする方が良い)。これは、インタラクティブなリベース ツールを使用して行います。このツールを使用すると、コミットをスカッシュしたり、コミットを削除したり、メッセージを言い換えたりgit rebase -i HEAD~10できます~-

Git でのインタラクティブなリベース

ただし注意して、このツールを「慎重に」使用してください。一度に 1 つの squash/delete/reorder を実行し、終了してそのコミットを保存してから、ツールに再度入ります。コミットが連続していない場合は、それらを並べ替えることができます (必要に応じてスカッシュします)。ここでも実際にコミットを削除できますが、そうするときは自分が何をしているのかを確認する必要があります!

フォーク

Git リポジトリでのコラボレーションには、主に 2 つの方法があります。1 つ目は、上で詳述したように、人々がプルしたりプッシュしたりするブランチを介して直接行われます。これらのコラボレーターは、リモート リポジトリに登録された SSH キーを持っています。これにより、そのリポジトリに直接プッシュできます。欠点は、ユーザーのリストを維持する必要があることです。もう 1 つのアプローチであるフォークでは、誰でもリポジトリを「フォーク」して、基本的に自分の Git リポジトリ アカウントにローカル コピーを作成できます。その後、彼らは変更を加えることができ、終了したら「プル リクエスト」(実際には、彼らからの「プッシュ」と実際のリポジトリ管理者への「プル」リクエスト) を送信して、コードを受け入れてもらいます。

フォークを使用するこの 2 番目の方法では、誰かがリポジトリのユーザーのリストを維持する必要はありません。


GitHub

GitHub (リモート リポジトリ) は、そのようなリポジトリがある (または追加されている) 場合に、コミットされた変更を通常プッシュおよびプルするリモート ソースであるため、ローカルとリモートは実際にはまったく異なります。リモート リポジトリは.git、リモート サーバー上に存在するディレクトリ構造であると考えることができます。

「フォーク」すると (GitHub Web ブラウザー GUI でこのボタンをクリックできます) GitHub アカウントフォークボタンのイメージにコードのコピー (「クローン」) が作成されます。初めて実行するときは少し微妙かもしれないので、コードベースが誰のリポジトリの下にリストされているかを確認してください-元の所有者または「フォークされた」あなたと、たとえば、次のように:

フォークされたリポジトリの名前のイメージ

ローカル コピーを取得したら、必要に応じて変更を加えることができます (ローカル マシンにプル アンド プッシュすることにより)。完了したら、元のリポジトリの所有者/管理者に「プル リクエスト」を送信します (空想に聞こえますが、実際にはこれをクリックするだけです: プルリクエストボタンのイメージ)。彼らはそれを「プル」します。

チームが共同でコードを作成する場合、より一般的なのは、リポジトリを「複製」することです (リポジトリのメイン画面で「コピー」アイコンをクリックします)。次に、ローカルで入力git clone して貼り付けます。これにより、ローカルにセットアップされ、(共有) GitHub の場所にプッシュおよびプルすることもできます。

クローン

GitHub のセクションで示されているように、クローンはリポジトリのコピーです。git cloneリモート リポジトリがある場合、その URL に対してコマンドを発行すると、最終的にリポジトリのローカル コピーまたはクローンが作成されます。このクローンには、ファイル、マスター ブランチ、その他のブランチ、既存のすべてのコミット、シバン全体のすべてが含まれています追加とコミットを行うのはこのクローンであり、リモートリポジトリ自体がそれらのコミットをプッシュするものです。SVN、PVCS、CVS などのより伝統的な CVS (コード バージョン管理システム) とは対照的に、Git (および Mercurial などのそれに類似したシステム) を DVCS (分散バージョン管理システム) にするのは、このローカル/リモートの概念です。リモートリポジトリに直接コミットします。

視覚化


核となる概念の視覚化は、 http://marklodato.github.com/visual-git-guide/index-en.htmlおよびhttp://ndpsoftware.com/git-cheatsheet.html#loc=indexで見ることができます。

変更がどのように機能しているかを視覚的に表示したい場合は、私が「地下鉄マップ」(特にロンドン地下鉄)と呼んでいる GUI を備えたビジュアル ツールgitg( macOS 用) に勝るものはありません。誰が何をしたかを示すのに最適です。gitx物事がどのように変化し、分岐し、合併したかなど。

また、変更の追加、コミット、および管理にも使用できます。

gitg/gitx インターフェイスのイメージ

gitg/gitx はごくわずかですが、GUI ツールの数は増え続けています。多くの Mac ユーザーは、brotherbard の gitx のフォークを使用しています。Linux の場合、優れたオプションは、直感的でありながら強力なインターフェイスを備えた smart-git です。

smart-git GUI のイメージ

GUI ツールを使用しても、おそらくコマンド ラインで多くのコマンドを実行することに注意してください。

このために、ファイルに次のエイリアスがあります (端末セッションごと~/.bash_aliasesにファイルから呼び出されます)。~/.bashrc

# git
alias g='git status'
alias gcob='git checkout -b '
alias gcom='git checkout master'
alias gd='git diff'
alias gf='git fetch'
alias gfrm='git fetch; git reset --hard origin/master'
alias gg='git grep '
alias gits='alias | grep "^alias g.*git.*$"'
alias gl='git log'
alias gl1='git log --oneline'
alias glf='git log --name-status'
alias glp='git log -p'
alias gpull='git pull '
alias gpush='git push '

そして、ファイルに次の「gitエイリアス」があり~/.gitconfigます-なぜこれらがあるのですか?
分岐補完(TABキーを使用)が機能するように!

したがって、これらは次のとおりです。

[alias]
  co = checkout
  cob = checkout -b

使用例: git co [branch]<- ブランチのタブ補完が機能します。

GUI学習ツール

https://learngitbranching.js.org/は、基本概念の一部を学習するのに役立つ場合があります。スクリーンショット: ビデオ: https://youtu.be/23JqqcLPss0ここに画像の説明を入力

最後に、7 つの重要な命の恩人です。

  1. 変更を加え、追加してコミットします (ただし、プッシュしないでください)。あなたはマスターにいることに気づきます!

     git reset [filename(s)]
     git checkout -b [name_for_a_new_branch]
     git add [file(s)]
     git commit -m "A useful message"
    
     Voila!  You've moved that 'master' commit to its own branch !
    
  2. ローカル ブランチで作業しているときにいくつかのファイルを台無しにしてしまい、前回実行したときの状態に戻したいだけですgit pull

     git reset --hard origin/master  # You will need to be comfortable doing this!
    
  3. ローカルで変更を開始し、半ダースのファイルを編集すると、まだ master (または別の) ブランチにいます。

     git checkout -b new_branch_name  # just create a new branch
     git add .                      # add the changes files
     git commit -m"your message"    # and commit them
    
  4. 現在のブランチで特定のファイルを台無しにして、基本的にそのファイルを最後にリモート リポジトリからプルしたときの状態に「リセット」(変更を失う) したい場合:

     git checkout your/directories/filename
    

    これにより、実際にファイルがリセットされます (多くの Git コマンドと同様に、ここで行っていることから適切な名前が付けられていません)。

  5. git resetローカルでいくつかの変更を行い、またはを実行している間にそれらを失わないようにしたい場合: Git で失敗したり、重要な情報を失ったりする可能性があるかどうかわからない場合rebase、プロジェクト全体 ( ) の手動コピーを作成することがよくあります。cp -r ../my_project ~/変化します。

  6. あなたはリベースしていますが、物事はめちゃくちゃになります:

     git rebase --abort # To abandon interactive rebase and merge issues
    
  7. Git ブランチをPS1プロンプトに追加します ( https://unix.stackexchange.com/a/127800/10043を参照)。

    プロンプトのイメージ

    支店はselenium_rspec_conversionです。

于 2012-02-09T02:09:38.643 に答える
373

クローンは、リポジトリの単なるコピーです。表面的には、その結果は、svn checkout他のリポジトリからソース コードをダウンロードする場合と同じです。Subversion のような一元化された VCS と Git のような DVCS の違いは、Git では、クローンを作成するときに、すべての履歴とブランチを含むソース リポジトリ全体を実際にコピーしていることです。これで、マシンに新しいリポジトリが作成され、作成したすべてのコミットがそのリポジトリに入ります。これらのコミットを別のリポジトリ (または元のリポジトリ) にプッシュするか、リポジトリが公開されている場合は誰かがコミットをプルするまで、誰も変更を確認できません。

ブランチは、リポジトリ内にあるものです。概念的には、開発のスレッドを表します。通常、マスター ブランチがありますが、機能 xyz に取り組んでいるブランチと、バグ abc を修正する別のブランチがある場合もあります。ブランチをチェックアウトすると、行ったコミットはそのブランチに残り、問題のブランチにマージまたはリベースするまで他のブランチと共有されません。もちろん、ブランチがどのように実装されているかの基礎となるモデルを見るまでは、ブランチに関して Git は少し奇妙に思えます。自分で説明するのではなく (すでに言いすぎた、と思います)、Git の Web サイトから引用した、Git がどのようにブランチとコミットをモデル化するかについての「コンピューター サイエンス」の説明にリンクします。

http://eagain.net/articles/git-for-computer-scientists/

フォークは実際には Git の概念ではなく、より政治的/社会的なアイデアです。つまり、プロジェクトの進行状況に満足していない人がいる場合は、ソース コードを取得して、元の開発者とは別に自分で作業することができます。それはフォークと見なされます。Git では、誰もがソース コードの独自の "マスター" コピーを既に持っているため、簡単にフォークできます。そのため、元のプロジェクト開発者との関係を断ち切るだけで済み、SVN の場合のように共有リポジトリから履歴をエクスポートする必要がありません。 .

編集:GitHubなどのサイトで使用されている「フォーク」の現代的な定義を知らなかったので、詳細については、コメントと私の以下のMichael Durrantの回答をご覧ください。

于 2010-07-25T16:27:12.790 に答える
143

以下は、すべてがどのように組み合わされているかを示す Oliver Steele のイメージです。

ここに画像の説明を入力

于 2013-01-22T17:12:31.590 に答える
10

フォーク対。クローン - どちらもコピーを意味する 2 つの単語

この図 を見てください。(元はhttp://www.dataschool.io/content/images/2014/Mar/github1.pngから)。

.-------------------------.     1. Fork     .-------------------------.
| Your GitHub repo        | <-------------- | Joe's GitHub repo       |
| github.com/you/coolgame |                 | github.com/joe/coolgame |
| ----------------------- | 7. Pull Request | ----------------------- |
| master -> c224ff7       | --------------> | master -> c224ff7 (c)   |
| anidea -> 884faa1 (a)   |                 | anidea -> 884faa1 (b)   |
'-------------------------'                 '-------------------------'
    |                 ^
    | 2. Clone        |
    |                 |
    |                 |
    |                 |
    |                 |
    |                 | 6. Push (anidea => origin/anidea)
    v                 |
.-------------------------.
| Your computer           |  3. Create branch 'anidea'
| $HOME/coolgame          |
| ----------------------- |  4. Update a file
| master -> c224ff7       |
| anidea -> 884faa1       |  5. Commit (to 'anidea')
'-------------------------'

(a) - after you have pushed it
(b) - after Joe has accepted it
(c) - eventually Joe might merge 'anidea' (make 'master -> 884faa1')

フォーク

  • Joe's にリンクするリモート リポジトリ (クラウド) へのコピー
  • ローカル リポジトリにクローンして F*%$-up できるコピー
  • 完了したら、リモコンにプッシュバックできます
  • 次に、プルリクエストをクリックして、Joe にプロジェクトで使用するかどうかを尋ねることができます。

クローン

  • ローカル リポジトリ (ハード ドライブ) へのコピー
于 2016-09-02T19:08:59.773 に答える
6

他の人に追加するために、フォークに固有のメモ。

技術的には、レポのクローン作成とレポのフォークは同じことです。行う:

git clone $some_other_repo

そして、あなたは背中を叩くことができます---あなたは他のレポをフォークしました。

VCS としての Git は、実際にはフォークのクローン作成がすべてです。cgit などのリモート UI を使用して「ブラウジングするだけ」を除けば、ある時点でレポをフォークして複製する必要のない git レポとはほとんど関係ありません。

でも、

  • 誰かが私がレポ X をフォークしたと言うとき、彼らはレポのクローンを別の場所に作成し、他の人に公開することを意図したことを意味します。たとえば、いくつかの実験を示したり、別のアクセス制御メカニズムを適用したりします (たとえば、 Github にアクセスできますが、コラボレーションには社内アカウントが必要です)。

    事実: レポはおそらく 以外のコマンドで作成され git clone、誰かのラップトップではなくサーバー上のどこかにホストされている可能性が高く、おそらくわずかに異なる形式を持っています (これは「ベアレポ」です。つまり、作業ツリーはありません)。すべて技術的な詳細です。

    ブランチ、タグ、またはコミットの異なるセットが含まれる可能性が最も高いという事実は、おそらく最初にそれを行った理由です。

    (「フォーク」をクリックしたときに Github が行うことは、シュガーを追加してクローンを作成することです。レポをクローンし、アカウントの下に置き、どこかに「フォークされた」を記録し、「アップストリーム」という名前のリモートを追加します。素敵なアニメーションを再生します。)

  • 私がレポ X をクローンしたと誰かが言うとき、彼らはレポのクローンをラップトップまたはデスクトップ上でローカルに作成したことを意味します。

Git の優れた点は、これらすべてが完全に適合することです。これらのリポジトリはすべて、ブロックコミット チェーンの共通部分を共有するため、これらすべてのリポジトリ間で変更を安全にマージできます (以下の注を参照)。


注:チェーンの共通部分を書き換えず、変更が競合しない限り、「安全に」。

于 2015-07-23T16:51:37.707 に答える