Ubah basis cabang

145

Saya punya pohon seperti ini:

(commit 1) - master
                \-- (commit 2) - (commit 3) - demo
                                                \-- (commit 4) - (commit 5) - PRO

dan saya harus memindahkan cabang PRO ke master

(commit 1) - master
                |-- (commit 2) - (commit 3) - demo
                \-- (commit 4) - (commit 5) - PRO

Saya sudah mencoba git rebase masterdari cabang PRO, tetapi tidak ada yang terjadi.

Untuk memperjelas : Saya bekerja di master dan kemudian saya harus membuat demo produk ( git checkout -b demodan beberapa komitmen). Kemudian, secara tidak sengaja, saya membuat cabang lain dari demo ( git checkout -b PROdan beberapa komit) dan sekarang saya perlu memindahkan cabang PRO untuk menguasai dan membiarkan demo tetap utuh. Pada akhirnya, baik demo maupun PRO akan hang dari master.

Ivan
sumber
kemungkinan duplikat dari titik perubahan cabang
Wladimir Palant

Jawaban:

281

Gunakan --ontountuk itu:

git rebase --onto newBase oldBase feature/branch

Mengingat kasus Anda:

git checkout PRO # Just to be clear which branch to be on.
git rebase --onto master demo PRO

Pada dasarnya, Anda mengambil semua komit dari setelah demohingga PRO, dan rebase mereka ke masterkomit.

loganfsmyth
sumber
Apakah itu juga cara untuk pergi jika situasinya berlawanan? == Saya checkout -b dari master cabang kedua, tapi saya ingin melakukannya dari yang pertama. Jadi saya lakukan git rebase --onto first-branch second-branch second-branchtetapi saya tidak mendapatkan sintaks
Fla
1
@Fla dalam hal itu, itu akan menjadigit rebase --onto first-branch master second-branch
nVitius
9
Saya membaca ini panduan tentang --onto, dan bagaimana mereka menulis membantu sayagit rebase --onto newBase oldBase feature/branch
gabe
@ PhilipRego Itu tidak benar. origin/newBaseadalah nama cabang, seperti newBasedalam contoh saya. Itu hanya akan tergantung jika Anda memunculkan kembali ke cabang yang ada di repositori lokal Anda ( newBase), atau yang ada di remote ( origin/newBase).
loganfsmyth
@ PhilipRego Itu bukan hal yang independen. newBaseadalah nama cabang lokal, dan origin/newBasenama cabang jarak jauh. Yang mana yang Anda inginkan tergantung pada apa yang Anda inginkan. Bukannya seseorang bekerja dan yang lain tidak, itu karena mereka mengubah hal yang berbeda. Pertanyaan aslinya tidak pernah menyebutkan remote, jadi menggunakan remote pada contoh saya tidak akan cocok dengan pertanyaan yang diajukan.
loganfsmyth
22

Saya akan mencoba untuk menjadi generik yang saya bisa. Pertama, pastikan Anda berada di cabang yang diinginkan:

git checkout current-branch

Kemudian gunakan perintah berikut (di mana new-base-branchcabang yang Anda inginkan menjadi basis baru Anda, dan current-base-branchcabang yang merupakan basis Anda saat ini.)

git rebase --onto new-base-branch current-base-branch

Jika Anda tidak memiliki konflik, maka hebat - Anda selesai. Jika Anda melakukannya (dalam kebanyakan kasus), silakan baca terus.

Konflik mungkin timbul, dan Anda harus menyelesaikannya secara manual. Git sekarang mencoba melakukan "penggabungan 3 arah" antara Anda current-branch, current-base-branchdan new-base-branch. Secara kasar ini adalah bagaimana git akan bekerja secara internal:

  1. Git akan rebase pertama current-base-branchdi atas new-base-branch. Mungkin ada konflik; yang harus Anda selesaikan secara manual. Setelah itu selesai, biasanya Anda lakukan git add .dan git rebase --continue. Ini akan membuat komitmen sementara baru temp-commit-hashuntuk ini.

  2. Setelah ini, Git sekarang akan rebase Anda current-branchdi atas temp-commit-hash. Mungkin ada konflik lebih lanjut dan lagi Anda harus menyelesaikannya secara manual. Setelah selesai, Anda melanjutkan lagi dengan git add .dan git rebase --continue, setelah itu Anda berhasil rebased Anda current-branchdi atas new-base-branch.


Catatan: Jika Anda mulai mengacaukan, maka Anda dapat melakukannya git rebase --abortkapan saja selama proses rebase dan kembali ke titik awal.

TABUT
sumber
The rebaseperintah seperti yang diposting hanya memberi saya "fatal: hulu tidak valid 'saat-base-cabang'". Juga, mengapa bahkan perlu untuk memberi tahu GIT apa cabang induk saat ini dari cabang saat ini - bukankah seharusnya sudah mengetahui hal ini?
Matt Arnold
21

Checkout ke PROcabang, Salin hash commit tertua dari ( komit4 ) dan terbaru ( komit5 ) dan tempel di tempat lain:

$ git checkout PRO
$ git log            # see the commit history
# copy the oldest & latest commit-hash 

Hapus PROcabang (simpan cadangan hanya untuk keselamatan). Buat dan checkout ke PROcabang baru dari master:

$ git branch PRO.bac    # create a new branch PRO.bac = PRO as backup

$ git checkout master
$ git branch -D PRO     # delete the local PRO branch
$ git checkout -b PRO   # create and checkout to a new 'PRO' branch from 'master'

Ambil ( pilih ceri ) rentang komit dari PROcabang Sebelumnya ke PROcabang baru :

$ git cherry-pick commit4^..commit5   # cherry-pick range of commits
# note the '^' after commit4

Sekarang, jika semuanya baik-baik saja, maka lakukan paksa (-f) dorong ke remote PROcabang dan hapus PRO.baccabang lokal :

$ git log                  # check the commit history

$ git push -f origin HEAD  # replace the remote PRO by local PRO branch history
# git branch -D PRO.bac    # delete local PRO.bac branch
Sajib Khan
sumber
1

Saya memiliki pendekatan yang sedikit berbeda menggunakan reset dan simpanan yang menghindari menghapus dan menciptakan kembali cabang serta menghilangkan kebutuhan untuk beralih cabang:

$ git checkout PRO
$ git reset commit4 # This will set PROs HEAD to be at commit 4, and leave the modified commit 5 files in ur working index
$ git stash save -m "Commit message"
$ git reset commit 3
$ git stash save -m "Commit message"
$ git reset master --hard
$ git stash pop
$ git stash pop
$ git push --force # force if its already been push remotely

Dengan mereset cabang pada komit dengan komit, pada dasarnya Anda hanya memutar ulang bahwa cabang mencatat komit pada satu waktu.

madjase
sumber
Haruskah Anda menghapus ruang antara "komit" dan "3" di baris ke-4?
Alexis Wilke