web-dev-qa-db-ja.com

Gitを使って最新のコミットを新しいブランチに移動する

マスターすることをコミットした最後のコミットを新しいブランチに移動し、それらのコミットが行われる前にマスターを戻します。残念ながら、私のGit-fuはまだ十分に強力ではありません。

すなわちどうやってこれから行けますか

master A - B - C - D - E

これに?

newbranch     C - D - E
             /
master A - B 
4108

新しいブランチに移動する

警告: 最初のコマンドgit branch newbranchで新しいブランチを作成しているので、この方法はうまくいきます。コミットを 既存のブランチに移動したい場合 git reset --hard HEAD~3を実行する前に変更内容を既存のブランチにマージする必要があります(下記の既存のブランチへの移動を参照)。 最初に変更内容をマージしないと、変更内容は失われます。

他に状況が関係していない限り、これは分岐してロールバックすることで簡単に行えます。

# Note: Any changes not committed will be lost.
git branch newbranch      # Create a new branch, saving the desired commits
git reset --hard HEAD~3   # Move master back by 3 commits (GONE from master)
git checkout newbranch    # Go to the new branch that still has the desired commits

しかし、元に戻すコミット数を確認してください。あるいは、HEAD~3の代わりに、master(/ current)ブランチで「元に戻す」コミットのハッシュ(またはOrigin/masterのような参照)を指定することもできます。 :

git reset --hard a1b2c3d4

* 1あなたは only masterブランチからコミットを "失う"ことになるでしょう、しかし心配しないでください、あなたはそれらのコミットをnewbranchに持つでしょう!

警告: Gitバージョン2.0以降では、後で元の(master)ブランチに新しいブランチをgit rebaseした場合、繰り越されたコミットを失うことを避けるために明示的な--no-fork-pointオプションが必要になるかもしれません。 branch.autosetuprebase alwaysを設定すると、これが起こりやすくなります。詳細については、 John Mellorの回答 を参照してください。

既存のブランチに移動する

コミットを 既存のブランチ に移動したい場合は、このようになります。

git checkout existingbranch
git merge master
git checkout master
git reset --hard HEAD~3 # Go back 3 commits. You *will* lose uncommitted work.
git checkout existingbranch
5244
sykora

それがなぜうまくいくのか疑問に思う人のために(私が最初にいたように):

Cに戻り、DとEを新しいブランチに移動したいとします。これは、最初は次のようになります。

A-B-C-D-E (HEAD)
        ↑
      master

git branch newBranchの後:

    newBranch
        ↓
A-B-C-D-E (HEAD)
        ↑
      master

git reset --hard HEAD~2の後:

    newBranch
        ↓
A-B-C-D-E (HEAD)
    ↑
  master

分岐は単なるポインタなので、 master は最後のコミットを指しています。 newBranch を作ったとき、あなたは単に最後のコミットへの新しいポインタを作っただけです。それからgit resetを使って master ポインタを2コミット戻しました。しかし、あなたは newBranch を動かさなかったので、それはまだそれが最初に行ったコミットを指しています。

893
Ryan Lundy

一般に...

この場合、sykoraによって公開された方法が最良の選択肢です。しかし時にはそれが最も簡単ではなく、一般的な方法でもありません。一般的な方法では git cherry-pick を使います。

OPが望んでいることを達成するために、それは2段階のプロセスです。

ステップ1 - newbranchにあなたが望むmasterからのコミットを書き留めます

Execute

git checkout master
git log

(例えば3)のハッシュがnewbranchに必要なコミットをしていることに注意してください。ここで私は使用します:
Cコミット:9aa1233
Dコミット:453ac3d
Eコミット:612ecb3 

注: /最初の7文字または全コミットハッシュを使用できます

ステップ2 - それらをnewbranchに置く

git checkout newbranch
git cherry-pick 612ecb3
git cherry-pick 453ac3d
git cherry-pick 9aa1233

OR(Git 1.7.2以降では範囲を使用)

git checkout newbranch
git cherry-pick 612ecb3~1..9aa1233

git cherry-pick これら3つのコミットをnewbranchに適用します。

372
Ivan

たった2つのコマンドを使用してこれを実行するもう1つの方法。現在の作業ツリーもそのまま残します。

git checkout -b newbranch # switch to a new branch
git branch -f master HEAD~3 # make master point to some older commit

古いバージョン - 私がgit branch -fについて学ぶ前

git checkout -b newbranch # switch to a new branch
git Push . +HEAD~3:master # make master point to some older commit 

Push.にできるようにすることは、知っておくといいニースのトリックです。

275
aragaer

Git stashを使ったもっと簡単な解決法

以下の場合: 

  • あなたの主な目的はmasterをロールバックすることです。 
  • ファイルの変更を保存したいのですが、誤ったコミットメッセージを気にする必要はありません。
  • あなたはまだプッシュしていません、そして
  • あなたはこれが簡単で、一時的なブランチ、コミットハッシュ、そして他の頭痛の種で複雑ではないことを望みます。

それから、以下ははるかに簡単です(3つの誤ったコミットを持つブランチmasterから始めます)。

git reset HEAD~3
git stash
git checkout newbranch
git stash pop

行番号でこれが何をするのか

  1. 最後の3回のコミット(およびそのメッセージ)をmasterへの取り消しはしますが、作業ファイルはすべてそのまま残します。
  2. すべての作業ファイルの変更を隠して、master作業ツリーをHEAD〜3状態と完全に一致させます。
  3. 既存のブランチnewbranchに切り替えます
  4. 隠した変更を作業ディレクトリに適用し、隠しファイルをクリアします

通常どおりgit addおよびgit commitを使用できるようになりました。すべての新しいコミットはnewbranchに追加されます。 

これがしないこと

  • それはあなたの木を散らかっているランダムな一時的な枝を残さない
  • 誤ったコミットを保存したりメッセージをコミットしたりしません。 そのため、この新しいコミットに新しいコミットメッセージを追加する必要があります。

目標

OPは、目標は変更を失うことなく「コミットする前にマスターに戻す」ことであり、この解決策はそれを実現することであると述べました。

私は誤ってmasterではなくdevelopに誤ってコミットしたとき、少なくとも週に1回これを行います。通常、ロールバックするコミットは1つだけです。その場合、1行目でgit reset HEAD^を使用するのが1つのコミットだけをロールバックするためのより簡単な方法です。 

マスターの変更を上流にプッシュした場合はこれをしないでください

他の誰かがそれらの変更を引っ張ったかもしれません。ローカルマスターのみを書き換える場合は、アップストリームにプッシュしても影響はありませんが、書き換えられた履歴を共同編集者にプッシュすると頭痛の種になる可能性があります。 

46
Slam

これは技術的な意味でそれらを「動かす」わけではありませんが、同じ効果があります。

A--B--C  (branch-foo)
 \    ^-- I wanted them here!
  \
   D--E--F--G  (branch-bar)
      ^--^--^-- Opps wrong branch!

While on branch-bar:
$ git reset --hard D # remember the SHAs for E, F, G (or E and G for a range)

A--B--C  (branch-foo)
 \
  \
   D-(E--F--G) detached
   ^-- (branch-bar)

Switch to branch-foo
$ git cherry-pick E..G

A--B--C--E'--F'--G' (branch-foo)
 \   E--F--G detached (This can be ignored)
  \ /
   D--H--I (branch-bar)

Now you won't need to worry about the detached branch because it is basically
like they are in the trash can waiting for the day it gets garbage collected.
Eventually some time in the far future it will look like:

A--B--C--E'--F'--G'--L--M--N--... (branch-foo)
 \
  \
   D--H--I--J--K--.... (branch-bar)
28
Sukima

履歴を書き換えずにこれを行うには(つまり、既にコミットをプッシュしている場合):

git checkout master
git revert <commitID(s)>
git checkout -b new-branch
git cherry-pick <commitID(s)>

両方の枝は、力を加えずに押すことができます。

21
teh_senaus

まさにこのような状況でした:

Branch one: A B C D E F     J   L M  
                       \ (Merge)
Branch two:             G I   K     N

私は実行しました:

git branch newbranch 
git reset --hard HEAD~8 
git checkout newbranch

私はHEADになると私は確信していましたが、コミットLは今です….

歴史の中で正しい場所に着地することを確実にするために、コミットのハッシュで作業することはより簡単です

git branch newbranch 
git reset --hard #########
git checkout newbranch
12
Darkglow

1)すべての変更をnew_branchに移動する新しいブランチを作成します。

git checkout -b new_branch

2)それから古い枝に戻ります。

git checkout master

3)git rebaseをする 

git rebase -i <short-hash-of-B-commit>

4)それから開かれたエディタは最後の3つのコミット情報を含みます。

...
pick <C's hash> C
pick <D's hash> D
pick <E's hash> E
...

5)これら3つのコミットすべてでpickdropに変更します。その後、保存してエディタを閉じます。 

...
drop <C's hash> C
drop <D's hash> D
drop <E's hash> E
...

6)最後の3コミットが現在のブランチから削除されました(master)。ブランチ名の前に+の印を付けてブランチを強く押します.

git Push Origin +master
2
rashok

どうやってこれから行けますか

A - B - C - D - E 
                |
                master

これに?

A - B - C - D - E 
    |           |
    master      newbranch

2つのコマンドで

  • git branch -mマスターnewbranch

与える

A - B - C - D - E 
                |
                newbranch

そして

  • gitブランチマスターB

与える

A - B - C - D - E
    |           |
    master      newbranch
1
user3070485

すべてのnpushedコミットを新しいブランチに移動する必要がある場合は、次のようにします。

  1. create a現在のブランチからの新しいブランチgit branch new-branch-name

  2. プッシュ your新しいブランチgit Push Origin new-branch-name

  3. 元に戻す yourold(current)branch最後のプッシュ/安定状態:git reset --hard Origin/old-branch-name

upstreamsではなくOriginを持っている人もいます。適切なupstreamを使用する必要があります

あなたはこれを行うことができます私が使ったことをちょうど3つの簡単なステップです。 

1)最近の更新をコミットしたい場所に新しいブランチを作成します。 

git branch <branch name> 

2)新しいブランチでコミットするための最近のコミットIDを見つけます。 

git log

3)そのコミットIDをコピーして、最新のコミットリストが一番上になるようにします。だからあなたはあなたのコミットを見つけることができます。あなたはまたメッセージを通してこれを見つけます。 

git cherry-pick d34bcef232f6c... 

コミットIDをいくつか指定することもできます。

git cherry-pick d34bcef...86d2aec

これであなたの仕事は終わりました。あなたが正しいIDと正しい枝を選んだなら、あなたは成功するでしょう。だから前にこれは注意してください。そうでなければ、別の問題が発生する可能性があります。 

今すぐあなたのコードをプッシュすることができます 

git Push

0
Pankaj Kumar