Чи є спосіб зменшити кількість комісій неінтерактивно?


Відповіді:


146

Переконайтесь, що ваше робоче дерево чисте

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

@wilhelmtell: Чудово! Тепер я міг би побудувати псевдонім git, наприклад, "mysquash 3 'деяке повідомлення" ", щоб скоротити це до однієї лінії?
Філліп

5
Якщо це лише кількість рядків:git reset --soft HEAD~3 && git commit -m "my message"
KingCrunch

7
@Phillip: Ви можете вбудувати функцію оболонки в псевдонім git. git config alias.mysquash '!f(){ git reset --soft HEAD~$1 && git commit ${2:+-m "$2"}; };f'. git mysquash 3 'some message'буде працювати, але я також налаштував його, тому я git musquash 3повністю опущу прапор -m, тож git commitу цьому випадку ви отримаєте інтерактивний інтерфейс користувача.
Лілі Баллард

3
Тільки для того, щоб було зрозуміло: це не те саме, що сквош. Сквош також зливає повідомлення про фіксацію. Якщо ви виконаєте м'який перезавантаження, ви втратите всі повідомлення комітетів. Якщо ви хочете зробити сквош, спробуйте stackoverflow.com/a/27697274/974186
René Link

1
@sebnukem - саме тоді ми намагаємось натиснути гілку, і пульт налаштовано для відхилення натискань на силу.
Авмохан

30

Мені особисто подобається рішення wilhelmtell :

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

Однак я зробив псевдонім з деякою перевіркою помилок, щоб ви могли це зробити:

git squash 3 'my commit message'

Я рекомендую налаштувати псевдоніми, які насправді запускають скрипти, щоб було легше (a) кодувати свої сценарії та (b) виконувати більш складну роботу з перевіркою помилок. Нижче представлений сценарій, який виконує роботу сквош, а далі - сценарій для налаштування псевдонімів Git.

Сценарій для збивання (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

Потім, щоб підключити цей скрипт squash.sh до псевдоніма git, зробіть інший сценарій для налаштування псевдонімів git, як-от так ( create_aliases.command або 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
Ви також можете поставити його в $PATHімені, git-squash.shі воно автоматично буде псевдонімом як git squash. Я не змінив вашу відповідь, на всякий випадок, коли є причина використовувати create-aiases.shсценарій, про який я не знаю.

Я в основному використовую сценарій create_aliases.command, щоб навіть наші прем’єр-міністри та дизайнери могли легко налаштувати. Просто двічі клацніть по скрипту, і всі вони встановлені (тим більше, що у мене є сценарій налаштування в нашому репо, і відомий відносний шлях). Тоді їм навіть не потрібно перезапускати термінал.
n8tr

1
Я спробував це, і воно читає моє повідомлення про фіксацію як кількість сквошів і не вдається, тому що це не ціле число.
Ментос

1
Рішення було додати - після /squash.sh \ $ 1 \ $ 2 '
Мінтос,

1
Мені подобається ідея рішення, але коментар, зазначений вище, ще не врахований у рішенні. Між одиничною та подвійною цитатою має бути знак мінус.
physicalattraction

10

Щоб додати відповідь від wilhelmtell, я вважаю, що зручно перезавантажити HEAD~2та змінити команду HEAD~3:

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

Це об'єднає всі зобов’язання до HEAD~3комісії та використає її повідомлення про фіксацію. Не забудьте почати з чистого робочого дерева.


2
Це правильна відповідь, оскільки вона скорочує серію комітетів, що ведуть до голови, і вона використовує повідомлення першого фіксу. Він не інтерактивний.
Ландон Кун

9

Я використав:

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

Працював зовсім чудово. Просто не намагайтеся мати журнал фіксування з рядком, який починається з "вибору" :)


На жаль, це не працює для мене в Windows. Ще отримайте інтерактивний редактор.
abergmeier

3

Використовуйте таку команду, щоб скинути останні 4 коміти в межах останнього комітету:

git squash 4

З псевдонімом:

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 

З https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig


Ви не вказали, яка ОС / оболонка використовується тут. Це рішення, ймовірно, не буде працювати для всіх інших настільних комп'ютерів, якими користуються люди.
Рік-777

так, ви повинні використовувати для цього linux / bash | zsh
brauliobo

2

Ось один вкладиш для скріплення останніх 2 комітів. У цьому прикладі повідомлення другого останнього комітету буде збережено. Ви можете змінити повідомлення за своїм бажанням.

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

Ця команда буде дуже корисною, якщо ви створите псевдонім для цієї команди та використовуєте псевдонім замість цього.


1

Збивати все, оскільки гілка була роздвоєна від господаря:

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

--reedit-message=HEADвикористовуватиме повідомлення останнього коміту, яке не є частиною сквош . Це, швидше за все, не той, який ви хочете. Щоб скоріше включити повідомлення першої комісії , або (1) замініть HEADхеш коміту, для якого потрібно повідомлення, або (2) перейдіть до першої комісії, яка буде включена і git commit --amend --reedit-message=HEAD. Ось що робить гармонійна відповідь.
Майлан

-1

Ви можете зблизитись

git rebase --ohead HEAD ~ 4 HEAD ~ master

Це передбачає, що ви перебуваєте у майстра з лінійною історією. Це не зовсім сквош, оскільки він відкидає проміжні коміти. Вам потрібно буде змінити нову HEAD, щоб змінити повідомлення про фіксацію.


Спасибі Грег; "Відкидання" Ви маєте на увазі, що ці проміжні комісії підлягають очищенню git gc?
Філіп

@Phillip Так, проміжні комісії стають сміттям, як і стара HEAD, тому що вона переписана, щоб мати HEAD~4її батьків.
Грег Бекон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.