Değişikliklerini korurken seçilen veri kaydı girişlerini Git havuzundan nasıl kaldırabilirim?


241

Girdileri taahhüt günlüğünde gösterilmemesi için, seçilen tamamlama günlük girişlerini doğrusal bir tamamlama ağacından kaldırmak istiyorum.

Taahhüt ağacım şöyle görünür:

R--A--B--C--D--E--HEAD

B ve C girişlerini kaldırma günlüğünde gösterilmeyecek şekilde kaldırmak istiyorum, ancak A'dan D'ye yapılan değişiklikler korunmalıdır. Belki tek bir taahhüt getirerek, B ve C'nin BC olması ve ağaç gibi görünmesi.

R--A--BC--D--E--HEAD

Veya ideal olarak, A doğrudan D'ye geldikten sonra. D 'A'dan B'ye, B'den C'ye ve C'den D'ye değişiklikleri temsil eder.

R--A--D'--E--HEAD

Mümkün mü? evet ise, nasıl?

Bu oldukça yeni bir proje olduğundan şu an için şubesi yok, bu yüzden de birleşmiyor.


@ xk0der: "taahhüt" burada doğru terimdir. rebaseeski / yeni taahhütleri kaldırabilir. "İşlem kaydı girişlerinin" ne anlama geldiğini bilmiyorum.
jfs

@JFSebastian "İşlem kaydı" ile ilgili bir sorun görmüyorum - Tüm işlemlerin kaydı. Ve günlükteki birkaç girişi silmek istedim - gerçek değişiklikleri korurken (taahhütler).
xk0der

@ xk0der: git komutları içeriğe adreslenebilir; örneğin, bir işlemdeki herhangi bir şeyi değiştirirseniz , örneğin günlük mesajı; yeni bir taahhüt yaratırsınız. Sen olabilir git en Git olmadan taahhüt okumak ve kendiniz görün .
jfs

@JFSebastian - Bağlantılar için teşekkürler - biliyorum - Ama bu teknik gerçekten karşılaştığım sorunu ve nasıl ortaya koyduğumu değiştiriyor mu? Sanırım hayır. Sonunda: "İşlem günlüğü iletilerini" kaldırmak istedim - "işlem değişiklikleri" ni kaldırmadan - Lütfen sorumu tekrar okuyun - özellikle ikinci paragraf. Daha fazla bilgi eklemek git logiçin "işlem kaydı" git-scm.com/docs/git-log . Ve bu kayıttaki iki girişten kurtulmak istedim - değişikliklerden değil.
xk0der

Yanıtlar:


273

git-rebase (1) tam olarak bunu yapar.

$ git rebase -i HEAD~5

git awsome-ness [git rebase - interactive] bir örnek içerir.

  1. Kullanmayın git-rebasekamu (uzaktan) kaydedilmesini üzerinde.
  2. Çalışma dizininizin temiz ( commitveya stashmevcut değişiklikleriniz) olduğundan emin olun .
  3. Yukarıdaki komutu çalıştırın. Başlatır $EDITOR.
  4. pickÖnce Cve Dtarafından değiştirin squash. C ve D'yi B'ye birleştirir. Bir taahhüdü silmek istiyorsanız, satırını silin.

Kaybolursanız, şunu yazın:

$ git rebase --abort  

Hızlı cevap için teşekkürler. Öyleyse A'ya bir ödeme yapıp yeniden bir taban git rebase -i D [A]mı yapıyorum ?
xk0der


3
Uzak depolarda nasıl yapabiliriz?
Eray

6
@Eray: sadece push -fdeğişiklikleriniz. Yalnız çalışmıyorsanız bunu yapma.
jfs

2
@ ripper234: git-rebaseBlog yayını için nokta manuel ve geri dönüş makinesine bağlantılar düzelttim .
jfs

75
# detach head and move to D commit
git checkout <SHA1-for-D>

# move HEAD to A, but leave the index and working tree as for D
git reset --soft <SHA1-for-A>

# Redo the D commit re-using the commit message, but now on top of A
git commit -C <SHA1-for-D>

# Re-apply everything from the old D onwards onto this new place 
git rebase --onto HEAD <SHA1-for-D> master

Bu da işe yarıyor ve yumuşak sıfırlamanın ne olduğunu anlamama yardımcı oldu. Kabul edilirse, "üst" cevap çok doğru ve daha kısa, ama bu cevap için de teşekkürler.
cgp

41

Aşağıda, yalnızca kaldırmak istediğiniz kesin kimliği bilerek belirli bir kesin kimliği kaldırmanın bir yolu bulunmaktadır.

git rebase --onto commit-id^ commit-id

Bunun, aslında taahhüt tarafından getirilen değişikliği kaldırdığını unutmayın.


7
Bu komuttaki fazladan KAFA, rebazın istenmeyen bir 'müstakil KAFA' ile bitmesine neden olacaktır. Gözetlenmelidir.
Frosty

3
Bu, taahhütlerimin getirdiği değişiklikleri geri alır, OP değişiklikleri korumak ister, sadece taahhütleri ezmek ister.
CB Bailey

1
-1 çünkü OP'nin istediği şeyi yapmaz (daha ziyade açıkça saklamak istediği bir şeyi yok eder).
Emil Styrke

1
OP'nin istediği şeyi yapmasa da, tam olarak ihtiyacım olan şeydi, bu yüzden yararlı bir cevap için +1.
Edvins

20

JF Sebastian'ın cevabını genişletmek için:

İşleme geçmişinizde kolayca her türlü değişikliği yapmak için git-rebase'i kullanabilirsiniz.

Git rebase --interactive komutunu çalıştırdıktan sonra, $ EDITOR ürününüzde aşağıdakileri elde edersiniz:

pick 366eca1 This has a huge file
pick d975b30 delete foo
pick 121802a delete bar
# Rebase 57d0b28..121802a onto 57d0b28
#
# 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

Taahhütlerin sırasını değiştirmek için satırları taşıyabilir ve bu taahhüdü kaldırmak için satırları silebilirsiniz. Veya iki taahhüdü tek bir taahhütte birleştirmek (ezmek) (önceki taahhüt yukarıdaki taahhüttür), taahhütleri düzenleyin (nelerin değiştiğini) veya taahhüt mesajlarını yeniden okuyabilirsiniz.

Bence seçim sadece bu taahhüdü yalnız bırakmak istediğiniz anlamına gelir.

(Örnek buradan )


14

Aşağıdaki örneklerde B ve C'yi etkileşimli olarak kaldırabilirsiniz :

git rebase --onto HEAD~5 HEAD~3 HEAD

veya sembolik olarak,

git rebase --onto A C HEAD

B ve C'deki değişikliklerin D'de olmayacağını unutmayın ; onlar gitmiş olacaklar .


Daha fazla bilgi için buraya bakın: sethrobertson.github.io/GitFixUm/fixup.html#remove_deep
Max

3

Bir yol daha,

git rebase -i ad0389efc1a79b1f9c4dd6061dca6edc1d5bb78a (C's hash)
and
git push origin master  -f

Eğer bir üs olarak kullanmak istediğiniz karma almak ve tüm kabak böylece Yukarıdaki komut interaktif yapmalıdır üst (eğer eski bırakmak gerekir) mesajları


2

A'nın SHA1'inden başka bir dal oluşturarak ve istenen değişiklikleri kiraz seçerek bu süreci daha güvenli ve daha kolay buluyorum, böylece bu yeni dalın nasıl göründüğünden emin olacağım. Bundan sonra, eski dalı kaldırmak ve yenisini yeniden adlandırmak kolaydır.

git checkout <SHA1 of A>
git log #verify looks good
git checkout -b rework
git cherry-pick <SHA1 of D>
....
git log #verify looks good
git branch -D <oldbranch>
git branch -m rework <oldbranch>

bunu yaparsanız E taahhüdünü de kaybedersiniz, değil mi? Anladığım kadarıyla, master'ı siliyorsunuz ve rework'i master olarak yeniden adlandırıyorsunuz (ABCDE akışının ana dal olduğunu düşünüyoruz).
Renan Bandeira

1

Sadece tüm insanların cevaplarını topladı: (git plz için yeni m sadece referans için kullanın)

taahhütleri silmek için git rebase

git günlüğü

-first check from which commit you want to rebase

git rebase -i KAFA ~ 1

-Here i want to rebase on the second last commit- commit count starts from '1')
-this will open the command line editor (called vim editor i guess)

Sonra ekran şöyle görünecektir:

pick 0c2236d Yeni satır eklendi.

2a1cd65..0c2236d'yi 2a1cd65'e yeniden adlandır (1 komut)

#

Komutlar:

p, pick = kullanma taahhüdü

r, reword = taahhüt kullan, ancak taahhüt mesajını düzenle

e, düzenle = taahhüt kullan, ancak değişikliği durdur

s, squash = taahhüt kullan, ancak önceki aktarmaya gir

f, fixup = "squash" gibi, ancak bu işlemin günlük iletisini sil

x, exec = shell kullanarak run komutu (satırın geri kalanı)

d, bırak = taahhüdü kaldır

#

Bu hatlar yeniden sipariş edilebilir; yukarıdan aşağıya doğru yürütülürler.

#

Burada bir satırı kaldırırsanız, KOMİTE KAYIP OLACAK

#

Ancak, her şeyi kaldırırsanız rebase iptal edilir.

#

Boş işlemlerin yorumlandığına dikkat edin ~ ~

~
~
~
~
~
~
~
~
~

Burada ilk satırı ihtiyacınıza göre değiştirin (yukarıda listelenen komutları kullanarak, örn. Taahhüdü kaldırmak için 'bırak' vb.) Düzenleme tamamlandıktan sonra, editörü kaydetmek ve çıkmak için ': x' tuşuna basın (bu sadece vim editörü içindir)

Ve sonra

git push

Gösteren sorun varsa, değişiklikleri uzaktan zorla zorlamanız gerekir (ÇOK KRİTİK: ekipte çalışıyorsanız itme zorlamayın)

git push -f başlangıç ​​noktası


-1

Bunun için git cherry-pick kullanabilirsiniz. 'cherry-pick' şu anki şubenize bir taahhüt uygulayacak.

o zaman yap

git rebase --hard <SHA1 of A>

sonra D ve E taahhütlerini uygulayın.

git cherry-pick <SHA1 of D>
git cherry-pick <SHA1 of E>

Bu, B ve C taahhüdünü atlayacaktır. D taahhüdünü B olmadan şubeye uygulamak imkansız olabileceğini söyledikten sonra YMMV.


2
OP, değişikliklerini silmek için değil B, C, D taahhütlerini birleştirmek istiyor.
jfs

3
Sanırım demek istediğin reset --hard, değil rebase --hard(ki mevcut değil)
Mauricio Scheffer
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.