Git'te son taahhüdü ikiye bölme


277

İki çalışma dalları, sahip ana ve forum ve ben sadece bazı değişiklikler yaptık forumu ben içine kiraz almak istediğinizi, şube ustası . Ama ne yazık ki, kiraz almak istediğim taahhüt de istemediğim bazı değişiklikler içeriyor.

Çözüm muhtemelen bir şekilde yanlış taahhüdü silmek ve bunu iki ayrı taahhütle değiştirmek olacaktır, biri master'da seçmek istediğim değişikliklerle ve oraya ait olmayan diğerleriyle.

Yapmayı denedim

git reset --hard HEAD^

tüm değişiklikleri sildi, bu yüzden geri dönmek zorunda kaldım

git reset ORIG_HEAD

Benim sorum şu, son taahhüdü iki ayrı komiteye bölmenin en iyi yolu nedir?

Yanıtlar:


332

Dizini kullanmalısınız. Karışık bir sıfırlama yaptıktan sonra (" git reset HEAD ^"), ilk değişiklik kümesini dizine ekleyin ve sonra bunları uygulayın. Sonra gerisini hallet.

Bir dosyada yapılan tüm değişiklikleri dizine eklemek için " git add " kullanabilirsiniz. Bir dosyada yapılan her değişikliği, yalnızca bir kısmını düzenlemek istemiyorsanız, "git add -p" kullanabilirsiniz.

Bir örnek görelim. Diyelim ki, aşağıdaki metni içeren dosyam adlı bir dosyam var:

something
something else
something again

Son işlemimde değiştirdim, böylece şimdi şöyle görünüyor:

1
something
something else
something again
2

Şimdi ikiye bölmek istediğime karar veriyorum ve ilk satırın eklenmesinin ilk işlemde olmasını ve son satırın eklenmesinin ikinci işlemde olmasını istiyorum.

İlk önce HEAD'in ebeveynine geri dönüyorum, ancak değişiklikleri dosya sisteminde tutmak istiyorum, bu yüzden argüman olmadan "git reset" kullanıyorum ("karma" reset olarak adlandırılacak):

$ git reset HEAD^
myfile: locally modified
$ cat myfile
1
something
something else
something again
2

Şimdi "git add -p" dizinine işlemek istediğim değişiklikleri eklemek için kullanıyorum (= ben onları sahne). "git add -p", dizine eklemesi gereken dosyadaki değişiklikleri soran etkileşimli bir araçtır.

$ git add -p myfile
diff --git a/myfile b/myfile
index 93db4cb..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,5 @@
+1
 something
 something else
 something again
+2
Stage this hunk [y,n,a,d,/,s,e,?]? s    # split this section into two!
Split into 2 hunks.
@@ -1,3 +1,4 @@
+1
 something
 something else
 something again
Stage this hunk [y,n,a,d,/,j,J,g,e,?]? y  # yes, I want to stage this
@@ -1,3 +2,4 @@
 something
 something else
 something again
+2
Stage this hunk [y,n,a,d,/,K,g,e,?]? n   # no, I don't want to stage this

Sonra bu ilk değişikliği taahhüt ederim:

$ git commit -m "Added first line"
[master cef3d4e] Added first line
 1 files changed, 1 insertions(+), 0 deletions(-)

Şimdi diğer tüm değişiklikleri (yani son satıra koymak "2" rakamı) taahhüt edebilirim:

$ git commit -am "Added last line"
[master 5e284e6] Added last line
 1 files changed, 1 insertions(+), 0 deletions(-)

Taahhütlerimizi görmek için günlüğü kontrol edelim:

$ git log -p -n2 | cat
Commit 5e284e652f5e05a47ad8883d9f59ed9817be59d8
Author: ...
Date: ...

    Added last line

Diff --git a/myfile b/myfile
Index f9e1a67..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -2,3 +2,4 @@
 something
 something else
 something again
+2

Commit cef3d4e0298dd5d279a911440bb72d39410e7898
Author: ...
Date: ...

    Added first line

Diff --git a/myfile b/myfile
Index 93db4cb..f9e1a67 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,4 @@
+1
 something
 something else
 something again

1
Geçtiğimiz bir buçuk hafta boyunca Mercurial'dan gitmeye yavaş yavaş alıştım ve sıfırladıktan sonra zorunluluktan git reset [--patch|-p] <commit>kurtulmak için kullanabileceğiniz kullanışlı bir kısayol komutu var git add -p. Haklı mıyım? Git'i kullanarak 1.7.9.5.
trojjer

2
İşte bu teknikle ilgili biraz daha fazla bilgi, daha eski bir taahhüt ise yeniden basma veya N taahhütlerini M taahhütlerine değiştirmeniz gerekiyor: emmanuelbernard.com/blog/2014/04/14/… .
Chris Westin

84

Hedefler:

  • Geçmişteki bir taahhüdü ( splitme) ikiye bölmek istiyorum .
  • Tamamlama mesajını korumak istiyorum .

Plan:

  1. daha önce birinden etkileşimli rebase splitme.
  2. düzenlemek splitme.
  3. Dosyaları ikinci bir işleme ayıracak şekilde sıfırlayın.
  4. Taahhüdü değiştirin, mesajı koruyun, gerektiği gibi değiştirin.
  5. İlk işlemden ayrılan dosyaları geri ekleyin.
  6. Yeni bir mesaj gönderin.
  7. Rebase'e devam et.

splitmeEn son taahhüt ise rebase adımları (1 ve 7) atlanabilir .

git rebase -i splitme^
# mark splitme commit with 'e'
git reset HEAD^ -- $files
git commit --amend
git add $files
git commit -m "commit with just some files"
git rebase --continue

Önce bölünmüş dosyaların işlenmesini isteseydim, tekrar -i'yi yeniden imleyip siparişi değiştirirdim

git rebase -i splitme^
# swap order of splitme and 'just some files'

1
git reset HEAD^bulmacanın eksik parçasıydı. -pÇok iyi çalışır . Teşekkürler!
Marius Gedminas

10
-- $filesTartışmayı not etmek önemlidir git reset. Yollar geçtikten sonra, git resetbu dosyaları başvurulan kesinleştirme durumuna geri yükler , ancak taahhütleri değiştirmez. Yollardan ayrılırsanız, bir sonraki adımda değiştirmek istediğiniz taahhüdü "kaybedersiniz".
düello belirteçleri

2
Bu yöntem, kabul edilen cevaba kıyasla ilk taahhüt mesajınızı tekrar kopyalayıp yapıştırmanızı engeller.
Calvin

Ayrıca: tüm dosyaları sıfırlamak istiyorsanız, tuşunu kullanın git reset HEAD^ -- .. Son derece şaşırtıcı bir şekilde, bu tam olarak davranışı değildirgit reset HEAD^ .
allidoiswin

52

Mevcut taahhüdü iki taahhütte değiştirmek için aşağıdakine benzer bir şey yapabilirsiniz.

Ya:

git reset --soft HEAD^

Bu, son taahhüdü geri alır ancak her şeyi sahneye bırakır. Daha sonra belirli dosyaları ayıklayabilirsiniz:

git reset -- file.file

İsteğe bağlı olarak bu dosyaların bölümlerini yeniden düzenleyin:

git add -p file.file

Yeni bir ilk taahhütte bulunun:

git commit

Aşama ve ikinci bir değişiklikteki değişikliklerin geri kalan kısmı:

git commit -a

Veya:

Son işlemden sonraki tüm değişiklikleri geri alın ve kaldırın:

git reset HEAD^

Değişikliklerin ilk turunu seçici olarak hazırlayın:

git add -p

Teslim Et:

git commit

Geri kalan değişiklikleri uygulayın:

git commit -a

(Her iki adımda da, yeni bir dosya ekleyen bir taahhüdü çözdüyseniz ve bunu ikinci yürütmeye eklemek istiyorsanız, commit -ayalnızca önceden izlenen dosyalarda aşamaları değiştirdiğinden dosyayı manuel olarak eklemeniz gerekir .)


22

Çalıştırın git gui, "Son işleme değiştir" radyo düğmesini seçin ve ilk işleme girmek istemediğiniz değişikliklerden (Teslim Et> Teslimden Çıkar veya Ctrl- U) değişiklikleri kaldırın . Sanırım bu konuda en kolay yol.

Yapabileceğiniz başka bir şey, değişikliği yapmadan ( git cherry-pick -n) ve daha sonra manuel olarak veya git guitaahhütte bulunmadan önce istenen değişiklikleri seçerek kiraz seçimidir.



13

Kimsenin önermediğine şaşırdım git cherry-pick -n forum. Bu, en son forumtaahhütten gelen değişiklikleri aşamalı hale getirecek, ancak taahhüt etmeyecektir - daha sonra resetihtiyacınız olmayan değişiklikleri ortadan kaldırabilir ve ne yapmak istediğinizi taahhüt edebilirsiniz.


3

Çift geri döndürme-ezme yöntemi

  1. İstenmeyen değişiklikleri kaldıran başka bir taahhütte bulunun. (Dosya başına ise, bu gerçekten kolaydır:git checkout HEAD~1 -- files with unwanted changes ve git commit. Değilse, karışık değişikliklere sahip dosyalar kısmen aşamalandırılabilir git reset fileve git add -p fileara adım olarak kullanılabilir.) Buna geri dönme deyin .
  2. git revert HEAD- İstenmeyen değişiklikleri geri ekleyen başka bir taahhütte bulunun. Bu çift ​​geri dönüş
  3. Şimdi yapılan 2 kaydedilmesini ki, ezmek (bölünmüş taahhüt üzerine ilk git rebase -i HEAD~3). Bu taahhüt şimdi istenmeyen değişikliklerden kurtuldu, çünkü bunlar ikinci taahhütte.

Yararları

  • Teslim mesajını korur
  • Ayrılma taahhüdü sonuncusu olmasa bile çalışır. Sadece istenmeyen değişikliklerin sonraki taahhütlerle çelişmemesini gerektirir

1

Kiraz toplama yaptığınız için şunları yapabilirsiniz:

  1. cherry-pickonunla --no-commitseçeneği eklendi.
  2. resetve kullanımı add --patch, add --editya da sadece addsaklamak istediğini sahneye.
  3. commit aşamalı değişiklikler.
    • Orijinal tamamlama mesajını yeniden kullanmak için, komuta --reuse-message=<old-commit-ref>veya --reedit-message=<old-commit-ref>seçenekleri ekleyebilirsiniz commit.
  4. İşaretlenmemiş değişiklikleri ile havaya uçurun reset --hard.

Başka bir yolla, orijinal tamamlama mesajını koruma veya düzenleme:

  1. cherry-pick orijinal normal olarak taahhüt.
  2. İstemediğiniz değişiklikleri addgeri alın ve geri dönüşü düzenlemek için kullanın .
    • Eklediğinizi kaldırıyorsanız bu adım kolay olur, ancak kaldırdıklarınızı eklerseniz veya değişikliği geri alırsanız biraz zor olur.
  3. commit --amend tersine çevirmeyi kiraz toplama taahhüdü üzerinde etkilemek.
    • Gerektiği gibi saklayabileceğiniz veya revize edebileceğiniz aynı taahhüt mesajını tekrar alacaksınız.

0

Bu, büyük bir taahhüdün olduğu ve az miktarda dosyanın yeni bir taahhüde taşınması gereken durumlar için hedeflenen başka bir çözüm olabilir. Bu, bir dizi<path>HEAD'deki son işlemden dosya çıkartılacaksa ve tümü yeni bir işleme . Birden fazla işlem yapılması gerekiyorsa, diğer çözümler kullanılabilir.

İlk olarak, sırasıyla değişiklikten önce ve değişiklikten sonra kodu geri döndürecek değişiklikleri içeren aşamalı ve etiketsiz alanlara yama yapın:

git reset HEAD^ <path>

$ git status
On branch <your-branch>
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   <path>

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   <path>

Ne olacağını anlamak için (ok ve yorumlar komutun bir parçası değildir):

git diff --cached   -> show staged changes to revert <path> to before HEAD
git diff            -> show unstaged changes to add current <path> changes

<path>Son işlemdeki değişiklikleri geri alma :

git commit --amend  -> reverts changes on HEAD by amending with staged changes

<path>Değişikliklerle yeni taahhütler oluşturun :

git commit -a -m "New Commit" -> adds new commit with unstaged changes

Bunun, son işlemden çıkarılan değişiklikleri içeren yeni bir işlem yaratma etkisi vardır.

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.