Etkileşimsiz olarak bir dizi taahhüdü ezmenin bir yolu var mı?


Yanıtlar:


147

Çalışma ağacınızın temiz olduğundan emin olun, sonra

git reset --soft HEAD~3
git commit -m 'new commit message'

@wilhelmtell: Harika! Şimdi bunu bir satıra indirgemek için "mysquash 3 'bir mesaj" "gibi bir git takma adı oluşturabilir miyim?
Phillip

5
Sadece satır sayısı ise:git reset --soft HEAD~3 && git commit -m "my message"
KingCrunch

7
@Phillip: Git takma adına bir kabuk işlevi yerleştirebilirsiniz. git config alias.mysquash '!f(){ git reset --soft HEAD~$1 && git commit ${2:+-m "$2"}; };f'. git mysquash 3 'some message'işe yarayacak, ancak ben de ince ayar yaptım, bu yüzden git musquash 3-m bayrağını tamamen çıkaracak, böylece git commitbu durumda etkileşimli kullanıcı arayüzünü alacaksınız .
Lily Ballard

3
Sadece açıklığa kavuşturmak için: Squash ile aynı şey değil. Squash ayrıca commit mesajlarını da birleştirecektir. Yazılımdan sıfırlama yaparsanız, işlemlerin tüm mesajlarını kaybedersiniz. Ezmek istiyorsanız stackoverflow.com/a/27697274/974186'yı
René Link

1
@sebnukem - İşte o zaman dalı itmeye çalışıyoruz ve uzaktan kumanda kuvvet itmelerini reddedecek şekilde yapılandırılıyor.
avmohan

30

Ben şahsen Wilhelmtell'in çözümünü beğeniyorum :

git reset --soft HEAD~3
git commit -m 'new commit message'

Ancak, bunu yapabilmeniz için bazı hata kontrolleri içeren bir takma ad yaptım:

git squash 3 'my commit message'

(A) komut dosyalarınızı kodlamanın ve (b) hata denetimiyle daha karmaşık işler yapmanın daha kolay olması için komut dosyalarını gerçekten çalıştıran takma adlar oluşturmanızı öneririm. Aşağıda squash işini yapan bir betik var ve bunun altında git takma adlarınızı ayarlamak için bir betik var.

Ezmek için komut dosyası (squash.sh)

#!/bin/bash
#

#get number of commits to squash
squashCount=$1

#get the commit message
shift
commitMsg=$@

#regular expression to verify that squash number is an integer
regex='^[0-9]+$'

echo "---------------------------------"
echo "Will squash $squashCount commits"
echo "Commit message will be '$commitMsg'"

echo "...validating input"
if ! [[ $squashCount =~ $regex ]]
then
    echo "Squash count must be an integer."
elif [ -z "$commitMsg" ]
then
    echo "Invalid commit message.  Make sure string is not empty"
else
    echo "...input looks good"
    echo "...proceeding to squash"
    git reset --soft HEAD~$squashCount
    git commit -m "$commitMsg"
    echo "...done"
fi

echo
exit 0

Sonra squash.sh betiğini bir git takma adına bağlamak için, git takma adlarınızı şu şekilde ayarlamak için başka bir betik oluşturun ( create_aliases.command veya create_aliases.sh ):

#!/bin/sh
echo '-----------------------'
echo 'adding git aliases....'
echo '-----------------------'
echo
git config --global alias.squash "!bash -c 'bash <path to scripts directory>/squash.sh \$1 \$2' -"
#add your other git aliases setup here
#and here
#etc.
echo '------------------------------------'
echo 'here is your global gitconfig file:'
echo '------------------------------------'
more ~/.gitconfig
echo 
echo
echo '----------------'
echo 'end of script...'
echo '----------------'

4
Ayrıca $PATHadlandırılmış olarak da koyabilirsiniz git-squash.shve otomatik olarak takma adı verilir git squash. Cevabınızı değiştirmedim, sadece create-aiases.shsenaryoyu kullanmak için farkında olmadığım bir neden varsa .

Temelde create_aliases.command komut dosyasını kullanıyorum, böylece proje yöneticilerimiz ve tasarımcılarımız bile kolayca kurulabilir. Sadece betiğe çift tıklayın ve hepsi ayarlandı (özellikle depomuzda kurulum betiğine sahip olduğum ve göreceli yol bilindiğinden). O zaman terminali yeniden başlatmaları bile gerekmez.
n8tr

1
Bunu denedim ve commit mesajımı squash sayısı olarak okuyor ve başarısız oluyor çünkü bu bir tamsayı değil.
Minthos

1
Çözüm, /squash.sh \ $ 1 \ $ 2 'sonrasına - eklemekti
sonrasına

1
Çözüm fikrini beğendim, ancak yukarıdaki yorum çözümde henüz dikkate alınmadı. Tek ve çift tırnak arasında bir eksi işareti olması gerekir.
Physicalattraction

10

Wilhelmtell'in cevabına eklemek için, yazılımdan sıfırlamayı HEAD~2ve ardından şunların taahhüdünü değiştirmeyi uygun buluyorum HEAD~3:

git reset --soft HEAD~2
git commit --all --amend --no-edit    

Bu, tüm taahhütleri HEAD~3commit ile birleştirecek ve commit mesajını kullanacaktır. Temiz, çalışan bir ağaçtan başladığınızdan emin olun.


2
Bu doğru cevaptır çünkü başa doğru giden bir dizi commit'i sıkıştırır ve 1. commit'in mesajını kullanır. Etkileşimli değildir.
Landon Kuhn

9

Kullandım:

EDITOR="sed -i '2,/^$/s/^pick\b/s/'" git rebase -i <ref>

Oldukça iyi çalıştı. Sadece "pick" ile başlayan bir satıra sahip bir commit günlüğü tutmaya çalışmayın :)


Ne yazık ki bu benim için Windows'ta çalışmıyor. Yine de etkileşimli düzenleyiciyi edinin.
abergmeier

3

Son kaydetme içindeki son 4 kaydetmeyi ezmek için aşağıdaki komutu kullanın:

git squash 4

Takma adla:

squash = !"f() { NL=$1; GIT_EDITOR=\"sed -i '2,$NL s/pick/squash/;/# This is the 2nd commit message:/,$ {d}'\"; git rebase -i HEAD~$NL; }; f"
sq = !git squash $1
sqpsf = !git squash $1 && git psf 

Gönderen https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig


Burada hangi işletim sisteminin / kabuğun kullanıldığını belirtmediniz. Bu çözüm muhtemelen insanların kullandığı diğer tüm masaüstü bilgisayarlar için işe yaramayacaktır.
Rick-777

evet, bunun için linux / bash | zsh kullanmalısınız
brauliobo

2

İşte son 2 kaydı ezmek için bir astar. Bu örnekte, ikinci son işlemin mesajı korunacaktır. Mesajı dilediğiniz gibi değiştirebilirsiniz.

git commit -am "$(git log -1 --skip=1 --pretty=%B | xargs && git reset --soft HEAD~2)"

Bu komut için bir takma ad oluşturup onun yerine takma adı kullanırsanız bu komut çok yararlı olacaktır.


1

Dal ustadan çatallandığından beri her şeyi ezmek için:

git reset --soft $(git merge-base --fork-point master) \
  && git commit --verbose --reedit-message=HEAD --reset-author

--reedit-message=HEADezmenin parçası olmayan son işlemenin mesajını kullanacaktır . Muhtemelen istediğin bu değil. Eklenecek ilk işlemenin mesajını almak için , ya (1)HEAD mesajını istediğiniz işlemenin karması ile değiştirin ya da (2) dahil edilecek ilk işleme atlayın ve git commit --amend --reedit-message=HEAD. Bu uyumlu 'cevabın yaptığı şeydir.
Maëlan

-1

İle oldukça yakınlaşabilirsin

git rebase --onto HEAD ~ 4 HEAD ~ usta

Bu, doğrusal bir geçmişe sahip olduğunuzu varsayar. Bu tam bir squash değil çünkü ara taahhütleri atıyor. Kaydetme mesajını değiştirmek için yeni HEAD'i değiştirmeniz gerekir.


Teşekkürler Greg; "iptaller" derken, bu ara taahhütlerin git gc tarafından temizlenmeye tabi olduğunu mu kastediyorsunuz?
Phillip

@Phillip Evet, ara işlemlerin yanı sıra eski HEAD de çöp haline gelir çünkü HEAD~4ebeveyni olarak yeniden yazılmıştır .
Greg Bacon
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.