13

私はローカルmasterdevelopブランチを持っています。すべての作業を行ってから、リリース用developにマージします。master必要な変更があるリモート ブランチがありますが、その変更の上upstream/masterに (共通の祖先を共有する) の変更をリベースし、developそれらを に戻したいと考えていdevelopます。私はすでにやったgit fetch upstream

リベースに関するGit本の章では、次のように述べています。

$ git checkout experiment
$ git rebase master

私の場合、私が(仮定する)意味は次のとおりです。

$ git checkout upstream/master
$ git rebase develop

しかし、その後、私はupsteam/master頭が離れた状態になります。ただし、 のマージを行う場合はupstream/master、 からdevelop行い、変更は ondevelopになります。

$ git checkout develop
$ git merge upstream/master

したがって、このリベースの方法は私には後ろ向きに思えます。マージがどのように機能するかと同様の変更を加えdevelopて、developブランチの変更をリベースしたいと思います。upstream/masterでリベースを行いupstream/master、競合を修正してから、追加し、隠して、にポップすることになっていますdevelopか?

4

3 に答える 3

16

リベースは実際には次のようになります。

git checkout develop
git rebase upstream/master

(読む必要があります:「現在のブランチをここにgit rebaseリベースし、ターゲットブランチの上にここに」)developupstream/master

最終結果は切り離されたヘッドではなく、新しく書き直されたdevelopブランチになります。

于 2013-10-05T17:48:49.990 に答える
14

最も簡単な (誰にとっても最も明白な) 方法は、master最初にブランチを更新してから、更新されたブランチにリベースすることmasterですorigin/master

$ git fetch origin                    # Get updates from remote.
$ git checkout master                 # Now bring master into sync:
$ git merge --ff-only origin/master   # if this fails you have stuff
                                      # in your master that they don't
                                      # have in theirs, and you need
                                      # to decide what to do about it

この時点で、すべてがうまくいき、masterorigin/masterが同じであれば ( や のようなグラフィカル ビューアで確認できるようgitkgit log --graph --oneline --decorate)、どのように機能するかgit rebase masterは明らかです。

しかし、実際にはそうする必要はありません。オンになっている間だけgit rebase origin/master、できdevelopます。(これはmasterunforward-ed のままになります — おそらくある時点で forward-ed したくなるでしょう — そのため、あまり節約にはなりませんが、今でより簡単に実行できます。)


長く退屈な「なぜ」の部分:git rebase長い形式では、ドキュメントではnewbaseupstream、 と説明されている 3 つのポイントが必要branchです。

git rebase ... [--onto <newbase>] [<upstream>] [<branch>]

のように引数を 1 つだけ指定すると、と の両方にgit rebase master名前が付けられ、が計算されます。は現在のブランチです (つまり、切り離してはなりません)。を省略した場合、が引数となります。したがって、今実行していて を実行すると、isと bothとare になります。upstreamnewbasebranchbranchHEAD--ontonewbaseupstreamdevelopgit rebase XbranchdevelopnewbaseupstreamX

実際には、リベース メソッドは次のとおりです (さまざまな内部最適化があり、reflog への影響は少し異なります)。

  1. チェックアウトbranch
  2. ポイントORIG_HEADへのコミットへの参照( )を保存しますbranch
  3. それを(a la git reset --hard)にリセットしますnewbase
  4. upstream..ORIG_HEAD1のすべてのコミットに対して(最も古いものから新しいものへ)、git cherry-pickそのコミットはそれを just-reset ブランチに追加します。

したがって、ドキュメントのように:

   Assume the following history exists and the current branch is "topic":

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

あなたgit rebase masterが得るとき:

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

(ここで行ったのは、man ページの例を取り上げ、元のコミットが「まだそこにある」ことを示すためにORIG_HEADラベルとを追加したことであり、それは への参照です)。HEAD=HEADtopic

では、あなたがあなたのものを持っていて、彼らがいくつかの追加の変更を加えたものを持っている場合はどうdevelopなりmasterますmasterか? それを描きましょう:

A -- B -- C                         master
          | \
          |   D                     origin/master
          |
          E -- F                    HEAD=develop

今あなたgit rebase origin/master

A -- B -- C                         master
          | \
          |   D                     origin/master
          |     \
          |       E' -- F'          HEAD=develop
          |
          E -- F                    ORIG_HEAD

ある時点で、最終的には自分自身もmasterコミットするポイントに移動しますD(そして をドロップしますORIG_HEAD):

A -- B -- C -- D                    master, origin/master
                 \
                   E' - F'          HEAD=develop

これは、一部のラベルが移動した場合と同じです。

ブランチ ラベルはこれですべてです。これらは単なるラベルです。各ラベルは 1 つの (単一の) コミットを指します。コミット自体は、以前のコミットを指し示します。これは、コミット ツリー (実際には「コミット DAG」) を構築するものです。


1 つの構文には、多くの「深い魔法」が隠されています。これは、「 labelから到達できないすべてのコミットが label から到達可能であることを意味します。これらは、「リベース」操作の前にon であり、 on ではなかったコミットであるため、まさにチェリーピックする必要があるコミットのセットです。一見時間ベースのシーケンスのように見えますが、これは一般的に人々の頭の中で機能しますが、コミット グラフ トポロジに基づいています。リポジトリ内の複数のコミット ツリー) は、「から到達可能なすべてのリビジョン.Git's X..YYXbranchupstreamA..BABB

于 2013-10-05T18:11:55.400 に答える