148

最近、Git を使い始めました。

Gitブックをオンラインで調べたところ、「Git Rebase」セクションで次のことがわかりました。

rebase コマンドを使用すると、あるブランチでコミットされたすべての変更を別のブランチで再生できます。

(引用: http://git-scm.com/book/en/Git-Branching-Rebasing )

これが git cherry-pickの正確な定義だと思いました (現在チェックアウトされているブランチにコミットまたはコミット オブジェクトのセットを再適用します)。

2つの違いは何ですか?

4

6 に答える 6

190

複数のコミットを適用できることを学んだ時からgit cherry-pick、その区別は確かにいくらか意味不明になりましたが、これは収斂進化と呼ばれるものです ;-)

真の違いは、両方のツールを作成するという当初の意図にあります。

  • git rebaseのタスクは、開発者がプライベート リポジトリで行った一連の変更を、上流のブランチのバージョン X に対して作成して、同じブランチのバージョン Y (Y > X) に転送することです。これにより、その一連のコミットのベースが効果的に変更されるため、「リベース」になります。

    (これにより、開発者は一連のコミットを任意のコミットに移植することもできますが、これはあまり明白ではありません。)

  • git cherry-pickある開発ラインから別の開発ラインに興味深いコミットをもたらすためのものです。古典的な例は、不安定な開発ブランチで行われたセキュリティ修正を安定した (メンテナンス) ブランチにバックポートするmergeことです。

    最初の登場以来、git cherry-pick一度に複数のコミットを 1 つずつ選択することができました。

したがって、おそらくこれら 2 つのコマンドの最も顕著な違いは、作業対象のブランチをどのように扱うかです。通常、別の場所からgit cherry-pickコミットを取得し、現在のブランチの上に適用して、新しいコミットを記録しますが、現在のブランチを取得して書き換えます。一連の独自のヒントが何らかの方法でコミットされます。はい、これは何ができるかについての非常に馬鹿げた説明ですが、一般的なアイデアを理解しようとする意図的なものです.git rebasegit rebase

議論されている使用例をさらに説明するために更新git rebaseします。

このような状況を踏まえて、
リベース前のリポジトリの状態
本書は次のように述べています。

ただし、別の方法があります。C3 で導入された変更のパッチを取得して、C4 の上に再適用することができます。Git では、これをリベースと呼びます。rebase コマンドを使用すると、あるブランチでコミットされたすべての変更を別のブランチに適用できます。

この例では、次を実行します。

$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command

ここでの「キャッチ」は、この例では、「実験」ブランチ (リベースの対象) がもともと「マスター」ブランチから分岐していたため、 C0 から C2 までのコミットを共有していることです。事実上、「実験」は「 master」から C2 まで、およびその上に C3 をコミットします。(これは考えられる最も単純なケースです。もちろん、「実験」には、元のベースの上に数十のコミットが含まれる可能性があります。)

「実験」を「マスター」の現在チップgit rebaseにリベースするように指示され、次のようになります。git rebase

  1. git merge-base"experiment" と "master" の両方で共有された最後のコミット (つまり、転換のポイントは何か) を確認するために実行します。C2です。
  2. 分岐点以降に行われたすべてのコミットを保存します。おもちゃの例では、ただの C3 です。
  3. HEAD (操作の実行が開始される前に「実験」の先端コミットを指す) を巻き戻し、「マスター」の先端を指すようにします — 私たちはそれにリベースしています。
  4. git apply保存された各コミットを ( のように) 順番に適用しようとします。おもちゃの例では、C3 という 1 つのコミットだけです。そのアプリケーションがコミット C3' を生成するとしましょう。
  5. すべてがうまくいった場合、「実験」参照が更新され、最後に保存されたコミットを適用した結果のコミット (この場合は C3') を指すようになります。

あなたの質問に戻りましょう。ご覧のとおり、ここでは技術的 git rebaseに実際に一連のコミットを「実験」から「マスター」の先端に移植しているため、その過程で「別のブランチ」が実際に存在することが正しくわかります。しかし要点は、「実験」からのヒントコミットが「実験」の新しいヒントコミットになり、ベースが変更されただけです。
合流後の様子

繰り返しますが、技術的には、git rebaseここに「マスター」からの特定のコミットが組み込まれていることがわかります。これは完全に正しいです。

于 2012-08-07T00:08:03.540 に答える
120

チェリーピックを使用すると、元のコミット/ブランチが残り、新しいコミットが作成されます。リベースを使用すると、リプレイされたコミットを指すブランチとともにブランチ全体が移動されます。

あなたが始めたとしましょう:

      A---B---C topic
     /
D---E---F---G master

リベース:

$ git rebase master topic

あなたは得る:

              A'--B'--C' topic
             /
D---E---F---G master

チェリーピック:

$ git checkout master -b topic_new
$ git cherry-pick A^..C

あなたは得る:

      A---B---C topic
     /
D---E---F---G master
             \
              A'--B'--C' topic_new

git の詳細については、この本にそのほとんどが含まれています(http://git-scm.com/book)

于 2012-12-28T16:43:08.573 に答える
19

チェリーピッキングは個々のコミットに対して機能します。

リベースを行うと、履歴内のすべてのコミットが、そこにないブランチの HEAD に適用されます。

于 2012-08-06T21:18:51.183 に答える
11

簡単な答え:

  • git cherry-pick はより「低レベル」です
  • そのため、git rebase をエミュレートできます。

上記の回答は良いです。相互関係を示すために例を挙げたかっただけです。

「git rebase」をこの一連のアクションに置き換えることはお勧めしません。これは単に「概念実証」であり、物事がどのように機能するかを理解するのに役立つことを願っています。

次のおもちゃのリポジトリがあるとします。

$ git log --graph --decorate --all --oneline
* 558be99 (test_branch_1) Test commit #7
* 21883bb Test commit #6
| * 7254931 (HEAD -> master) Test commit #5
| * 79fd6cb Test commit #4
| * 48c9b78 Test commit #3
| * da8a50f Test commit #2
|/
* f2fa606 Test commit #1

たとえば、test_branch_1 に含めたい master にいくつかの非常に重要な変更 (コミット #2 から #5) があるとします。通常、ブランチに切り替えて「git rebase master」を実行します。しかし、「git cherry-pick」しか装備していないふりをしているので、次のようにします。

$ git checkout 7254931                # Switch to master (7254931 <-- master <-- HEAD)
$ git cherry-pick 21883bb^..558be99   # Apply a range of commits (first commit is included, hence "^")    

これらすべての操作の後、コミット グラフは次のようになります。

* dd0d3b4 (HEAD) Test commit #7
* 8ccc132 Test commit #6
* 7254931 (master) Test commit #5
* 79fd6cb Test commit #4
* 48c9b78 Test commit #3
* da8a50f Test commit #2
| * 558be99 (test_branch_1) Test commit #7
| * 21883bb Test commit #6
|/
* f2fa606 Test commit #1

ご覧のとおり、コミット #6 と #7 は 7254931 (マスターのヒント コミット) に対して適用されました。HEAD は移動され、基本的にリベースされたブランチの先端であるコミットを指しています。あとは、古いブランチ ポインタを削除して、新しいブランチ ポインタを作成するだけです。

$ git branch -D test_branch_1
$ git checkout -b test_branch_1 dd0d3b4

test_branch_1は現在、最新のマスター位置からルート化されています。終わり!

于 2016-03-30T10:12:16.233 に答える