0

私がブランチに取り組んでいるとしましょうX。私が行った最近のコミットは20 minutes前のものです。ここで、組織の公式リポジトリからのコミットをマージしたかったのですが、そのコミットは約 20 日前に変更されました。

私のレポでコミットの正しい順序を(時間ごとに)維持しながら、そのコミットをマージできる方法はありますか。

現在、私がした場合git cherry-pick <sha1>、それはコミットをマージしましたが、HEAD.

編集

A1--A2--A3--A4--A5--A6--A7--HEAD ----master (official: `upstream`)

A1--A2--A4--A5--A6--A7--A8--A9--A10 ----mybranch (github repo : `origin`)

A1--A2--A4--A5--A6--A7--A8--A9--A10 ----mybranch (local repo on system)

My aim: Merge the upstream's `A3` commit **in its own place**:

A1--A2--**A3**--A4--A5--A6--A7--A8--A9--A10 ----mybranch (github repo : `origin`)

A1--A2--**A3**--A4--A5--A6--A7--A8--A9--A10 ----mybranch (local repo on system)

(NOT THIS):

A1--A2--A4--A5--A6--A7--A8--A9--A10--**A3**
4

3 に答える 3

0

rebaseそれは、またはよりチェリーピッキングを使用して可能ですが、ここでは詳しく説明しません。おそらく、すべきではないことを試みているからです。自分の歴史について嘘をつき、ある時点でそのコミットが自分のブランチの一部だったふりをしたいのはなぜですか?

単純にマージしgit log --date-orderて、コミットを正しい日付順で提供できます:)。

于 2013-07-25T02:47:16.890 に答える
0

可能ですが、新しいコミットを作成しないとできません。つまり、それA4以降のローカル コミットがローカルのみである場合は、リベースできます。ただし、それらが起源であるため、頭痛の種になります。

G私の理解が正しければ、これがあなたの状況で、 との間Bに挿入したいのですC

* H (upstream/master)
* G
* F
| * E (master, origin/master)
| * D
| * C
|/
* B
* A

重要な点は、コミットは祖先によって定義されるということです。つまり、Cはがその親であるという事実によって定義さBれます (これは にも当てはまりますF)。の上に新しいコミットを作成できますが、「 と の間にBコミットを挿入する」ということは、 の親を変更することを意味します。BCCCC

あなたが求めている歴史は確かに可能です(しかし、これは問題を引き起こします):

git rebase --onto G B E
git checkout -B master HEAD   # The '-B' option isn't related to the commit 'B'.

そのリベースが行うことは、 のB..E上で範囲をリプレイすることです。つまり、のパッチを の上で順番に再Gコミットします。あなたはこの状態になります:CDEG

* H (upstream/master)
| * E' (master)
| * D'
| * C'
|/
* G
* F
| * E (origin/master)
| * D 
| * C
|/
* B
* A

C', D',は, ,E'の同じ変更を表す新しいコミットですが、元の対応するものとは関係ありません。master と origin/master が分岐していることに注意してください。それらを統合するには、それらをマージする必要があり、その後、履歴に 、、が、として複製されます。CDECDEC'D'E'

この状況で統合Gするには、正しいことはそれをマージすることです:

git merge G

これはの不変部分であるため、 も引き込まGれます。コミットは履歴によって定義されます。のパッチだけを取り込みたい場合は、チェリーピックする必要があります。FGG

git cherry-pick G

ただし、リベースと同様に、コミットをチェリー ピックすると、元のパッチを使用して新しいコミットが作成されるため、履歴にコミットの重複が発生します。それが問題ない場合もあります: 特定のコミットがすぐに必要な場合 (たとえば、本番用のホットフィックス) があり、重複はそれを表しています。しかし、一般的には、それはあなたが望むものではなく、マージが進むべき道です。

于 2013-07-25T14:56:03.720 に答える
0

別の回答へのコメントに基づいて、開発は次のようになります。

C2 --- C3 --- C4 --- F2 --- C5       <-- master, origin/master (or similar)
   \
    W1 --- FX --- W2 --- W3 --- W4 --- W5  <-- workbranch

FX数週間前に作業ブランチに修正を書き、W1を介してコミットしW5ました。彼ら (誰が管理しているorigin/masterか、origin/featureまたはあなたがブランチで作業しているものは何でも) は、おそらく上記の他のコミット (C3を介してC5) と一緒に、最終的にそれをコミットするようになりました。これは別のコミットであるため (変更内容は同じですが)、 というラベルを付けましたF2

上にブランチをリベースできますが、必要に応じて、少なくともF2からの変更を取得する必要があります。それが必要な場合は、次のようにします。C3C4C5

$ git rebase -i master

あなたがあなたの中にいる間workbranch。修正FXは既に含まれているため (現在は と呼ばれています)、引き継ぐ変更のリストからF2それ (リベースを開始するときに編集しているファイル内の行) を削除してpickから、対話型リベースを実行します。もちろん、別のコミット (上記の ) に基づいているため、各コミットW1W5引き続き独自に機能することも確認する必要があります。C5そうでない場合は、別の作業を行いrebase -i、必要に応じて各コミットを修正する必要があります。また、リベースで競合が発生する可能性があり、手動で解決する必要があります。しかし、これがすべて機能すると仮定すると、次のようになります。

C2 --- C3 --- C4 --- F2 --- C5       <-- master, origin/master (or similar)
                              \
                               W1' --- W2' ... --- W5'  <-- workbranch

'(数学表記から借用した一重引用符は、これらがコミット、などと単に「同じことを行う」新しいコミットであることを示します。これは、コミットの既存のチェーンを取得し、新しいチェーンを作成することです。古いチェーンと「同じことをする」別の場所から開始するコミットの、古いチェーンからラベル (この場合は <code>workbranch) を削除し、それを新しいチェーンに貼り付けます。)W1W2rebase

運が良ければ、「余分な」コミット (C3およびそれC4以上) はありません。作業ブランチがコミット C2 から外れると、リモートの「メイン ライン」の次のコミットは修正 F2 になります。コミットW1が修正で問題なく機能する場合は、次のようにします。

$ git rebase -i <sha1-of-F2>

その内容は と同じであるpickため、 commitの行を再度削除します。この場合、次のようなコミット ツリーが得られます。FXF2

C2 --- F2 --- C5                     <-- master, origin/master (or similar)
          \
            W1' --- W2' --- W3' --- W4' --- W5'  <-- workbranch

いずれの場合も、ここでのポイントは同じです: 変更の新しいチェーン (あなたの "作業" ork) を作成し、origin/whatever"彼ら" がバグ修正コミットを commit として配置した時点または後にFXポイントをハングアップさせますF2。ここでの問題も同じです.C2から分岐したときに作業をテストし、新しいワークチェーンが他のコミットから分岐したため、作業の一部またはすべてが微妙に壊れている可能性があります.

注: リベース作業を行う場合、元の作業にラベルを貼り付けておくことができます。これにより、元の一連のコミット ( W1FXW2、 ... 上記) に簡単にアクセスできます。次のようにします。

git branch original-workbranch workbranch

リベースを開始する前に。「新しい」バージョンですべて問題ないことに満足したら、余分なラベルを削除できます。

git branch -D original-workbranch

この「保存」ステップを忘れた場合、または気にせず、後で元の作業ブランチを回復したい場合は、事後 (通常は約 90 日間) に「参照ログ」を介して実行できます (「参考文献」を参照git reflog --help)。その時点でより多くの仕事。

于 2013-07-25T03:22:26.373 に答える