Taahhütlerin yeniden sıralanması


105

Şu anda bir şube üzerinde çalışıyorum ve bazı taahhütlerin diğer şubelerle birleştirilmesini istiyorum:

    a-b-c-d-e-f-g (branchA)
   /
--o-x-x-x-x-x-x-x-x-x-x (master)
   \
    x-x-x-x-x (branchB)

(Harfler kaydetmeyi belirtir ve "x" alakasız işlemlerdir.)

Bununla birlikte, bazı taahhütleri bir araya getirmenin iyi bir fikir olacağını fark ettim. A, d, e ve g'yi tek bir yama halinde "birleştirmek" ve onu ustalaşmaya adamak istiyorum. B ve f işlemleri, şubeB'ye tek bir işlem olarak gitmelidir. Bunu başarmanın iyi bir yolu var mı?


4
Zaten verilen iki cevap doğru komuttan bahsediyor, ancak bence bu kadar basit bir görevle, burada StackOverflow'da gerçek talimatlar almaya değer, bu yüzden bazılarını yayınladım. (Bağlantı
kurulacak

Yanıtlar:


126

Aradığınız komut git rebase, özellikle -i/--interactiveseçenektir.

A dalında commit c'yi bırakmak istediğinizi varsayacağım ve gerçekten birleştirme yerine diğer taahhütleri diğer dallara taşımak istediğinizi kastediyorsunuz, çünkü birleşmeler basittir. A dalını manipüle ederek başlayalım.

git rebase -i <SHA1 of commit a>^ branchA

Bu ^, önceki kesinleştirme anlamına gelir, bu nedenle bu komut, "a" dan önce yürütmeyi temel olarak kullanarak şube A'yı yeniden temel almayı söyler. Git size bu aralıktaki işlemlerin bir listesini sunacak. Bunları yeniden sıralayın ve git'e uygun olanları ezmesini söyleyin:

pick c ...
pick a ...
squash d ...
squash e ...
squash g ...
pick b
squash f

Şimdi tarih şöyle görünmeli:

    c - [a+d+e+g] - [b+f] (branchA)
   /
--o-x-x-x-x-x-x-x-x-x-x (master)

Şimdi, şube B için yeni sıkıştırılmış b + f işlemini alalım.

git checkout branchB
git cherry-pick branchA  # cherry-pick one commit, the tip of branchA

Ve aynısı usta için a + d + e + g için:

git checkout master
git cherry-pick branchA^

Son olarak, branchA'yı c'yi gösterecek şekilde güncelleyin:

git branch -f branchA branchA^^

Şimdi sahip olmalıyız:

    c (branch A) - [a+d+e+g] - [b+f] (dangling commits)
   /
--o-x-x-x-x-x-x-x-x-x-x-[a+d+e+g] (master)
   \
    x-x-x-x-x-[b+f] (branchB)

Birden fazla işleminiz varsa, şubeler arasında hareket etmek istiyorsanız, yeniden temellemeyi (etkileşimsiz olarak) tekrar kullanabileceğinizi unutmayın:

# create a temporary branch
git branch fromAtoB branchA
# move branchA back two commits
git branch -f branchA branchA~2
# rebase those two commits onto branchB
git rebase --onto branchB branchA fromAtoB
# merge (fast-forward) these into branchB
git checkout branchB
git merge fromAtoB
# clean up
git branch -d fromAtoB

Son olarak, bir feragatname: Kayıtları, bazıları artık temiz bir şekilde uygulanmayacak şekilde yeniden düzenlemek oldukça mümkündür. Bunun nedeni, kötü bir sipariş seçmiş olmanız olabilir (yamayı uyguladığı özelliği tanıtmadan önce bir yama koymak); bu durumda rebase ( git rebase --abort) işlemini iptal etmek isteyeceksiniz . Aksi takdirde, çakışmaları akıllıca düzeltmeniz (tıpkı birleştirme çakışmalarında yaptığınız gibi), düzeltmeleri eklemeniz ve devam git rebase --continueetmek için koşmanız gerekir. Bu talimatlar, çakışma meydana geldiğinde yazdırılan hata mesajıyla da sağlanır.


git branch -f branchA branchA^^yanlıştan sonraki diyagram değil mi? Yani, diyagram ilk satırı, öyle ki, bu noktada c işaret ediyor branchA olmamalıdır c (branchA)olup c - [a+d+e+g] - [b+f] (branchA)?
ntc2

@enoksrd: Evet, bir hata var, ancak düzenlemenizde hatalar var. Burada bir şansım olduğunda düzelteceğim.
Cascabel

git branch -f branchA branchA^^Yapmak yerine neden git reset --hard <sha1 of c>A dalında yapamıyorsun ?
Mikhail Vasilyev

17
git rebase -i HEAD~3

3Yeniden sıralanması gereken işlemlerin sayısı nerede ( kaynak ).

Bu açılacaktır vi gelen kaydedilmesini listeleyen en eski için (üst) yeni (altta).
Şimdi satırları yeniden sıralayın , kaydedin ve düzenleyiciden çıkın .

ddpmevcut satırı aşağı
ddkP taşıyacak mevcut satırı yukarı taşıyacak ( kaynak )


9

git rebase --interactive istediğiniz komuttur.

Misal:

Mevcut durum şudur:

bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git status
On branch master
nothing to commit, working tree clean
bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git log --oneline
a6e3c6a (HEAD -> master) Fourth commit
9a24b81 Third commit
7bdfb68 Second commit
186d1e0 First commit

Kayıtları yeniden sıralamak istiyorum 9a24b81(Üçüncü işleme) ve 7bdfb68(İkinci kesinleştirme). Bunu yapmak için, önce değiştirmek istediğimiz ilk işlemden önce yürütmeyi bulurum . Bu commit'dir 186d1e0(İlk commit).

git rebase --interactive COMMIT-BEFORE-FIRST-COMMIT-WE-WANT-TO-CHANGEBu durumda yürütülecek komut şudur :

bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git rebase --interactive 186d1e0

Bu, varsayılan düzenleyicide aşağıdaki içeriğe sahip bir dosya açar:

pick 7bdfb68 Second commit
pick 9a24b81 Third commit
pick a6e3c6a Fourth commit

# Rebase 186d1e0..a6e3c6a onto 186d1e0 (3 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#

Dosyadaki commit'lerin sırasının git log için kullanılanın tersi olduğuna dikkat edin. Git logda, en son kayıt en üsttedir. Bu dosyada, en son kayıt en altta.

Dosyanın altındaki yorumda da açıklandığı gibi, yapabileceğim çeşitli şeyler var, örneğin kaydetme, bırakma ve yeniden sıralama gibi. Kayıtları yeniden sıralamak için dosyayı şöyle görünecek şekilde düzenlerim (alttaki yorumlar görüntülenmez):

pick 9a24b81 Third commit
pick 7bdfb68 Second commit
pick a6e3c6a Fourth commit

pickHer satır aracı "kullanımı (yani dahil) bu taahhüt" ve I ve Rebase komutlarla geçici dosyayı kaydetmektedir editörü çıktığınızda, git komutları yürütmek ve depo ve çalışma dizinini güncellenir başında komut:

$ git rebase --interactive 186d1e0
Successfully rebased and updated refs/heads/master.
bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git log --oneline
ba48fc9 (HEAD -> master) Fourth commit
119639c Second commit
9716581 Third commit
186d1e0 First commit

Yeniden yazılmış kayıt geçmişine dikkat edin.

Bağlantılar:


1
Eksiksiz ve bağımsız bir yanıt sağlamak için lütfen bağlantınızdan ilgili ayrıntıları ekleyin. SO "yalnızca bağlantı içeren yanıtlar" ı kaşlarını çatıyor. Özellikle, git rebase --interactiveOP'nin amacına ulaşmak için nasıl kullanılır ?
SherylHohman

İkinci bağlantı şu anda mevcut değil.
devsaw

Cevabı eksiksiz ve bağımsız hale getirmek için içerik eklendi. İkinci bağlantı kaldırıldı.
kodak


-1

git rebase istediğiniz şeydir. --İnteractive seçeneğine göz atın.


4
Eksiksiz ve bağımsız bir yanıt sağlamak için lütfen bağlantınızdan ilgili ayrıntıları ekleyin. SO "yalnızca bağlantı içeren yanıtlar" ı kaşlarını çatıyor.
SherylHohman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.