Опитвам се да смачкам набор от ангажименти - HEAD към HEAD~3. Има ли бърз начин да направя това или трябва да използвам rebase --interactive?
Има ли начин да се премахнат редица ангажименти неинтерактивно?
Отговори (8)
Тогава се уверете, че вашето работно дърво е чисто
git reset --soft HEAD~3
git commit -m 'new commit message'
git reset --soft HEAD~3 && git commit -m "my message"
- person KingCrunch; 02.09.2011
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
UI в този случай.
- person Lily Ballard; 02.09.2011
mu
имате предвид my
.
- person Acumenus; 22.04.2014
HEAD~3
, за да отрази последния изпратен ангажимент? Не искам да пиша 3
и т.н.
- person Acumenus; 22.04.2014
Аз лично харесвам решението на wilhelmtell:
git reset --soft HEAD~3
git commit -m 'new commit message'
Направих обаче псевдоним с известна проверка на грешки, за да можете да направите това:
git squash 3 'my commit message'
Препоръчвам да настроите псевдоними, които действително изпълняват скриптове, така че да е по-лесно (а) да кодирате вашите скриптове и (б) да извършвате по-сложна работа с проверка на грешки. По-долу е скрипт, който върши работата на скуош, а отдолу е скрипт за настройка на вашите 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 '----------------'
$PATH
с име git-squash.sh
и той автоматично ще бъде псевдоним като git squash
. Не промених отговора ви, само в случай, че има причина да използвам скрипта create-aiases.sh
, за която не знам.
- person ; 12.06.2014
-
. Също така, да, ще трябва да принудите натискането, ако вече сте натиснали предишните несмачкани комити. Препоръчвам да принудите push само към вашите собствени клонове, а не да правите това към главен клон.
- person n8tr; 27.10.2015
За да добавя към отговора от wilhelmtell намирам за удобно да нулирам меко до HEAD~2
и след това да променя ангажимента на HEAD~3
:
git reset --soft HEAD~2
git commit --all --amend --no-edit
Това ще обедини всички ангажименти към ангажимента HEAD~3
и ще използва неговото съобщение за ангажимент. Не забравяйте да започнете от чисто работещо дърво.
--all
в git commit
е ненужен, тъй като модифицираните файлове вече са поставени след меко нулиране. Документ за git commit --all
- person li ki; 17.06.2021
Използвах:
EDITOR="sed -i '2,/^$/s/^pick\b/s/'" git rebase -i <ref>
Работи доста добре. Просто не се опитвайте да имате дневник на комити с ред, който започва с "pick" :)
Използвайте следната команда, за да смачкате последните 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
Ето един ред, за да смачкате последните 2 комита. В този пример съобщението за предпоследния ангажимент ще бъде запазено. Можете да промените съобщението, както желаете.
git commit -am "$(git log -1 --skip=1 --pretty=%B | xargs && git reset --soft HEAD~2)"
Тази команда ще бъде много полезна, ако създадете псевдоним за тази команда и използвате псевдонима вместо това.
За да смачкате всичко, откакто клонът беше раздвоен от master:
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
. Ето какво прави хармоничният отговор.
- person Maëlan; 09.11.2018
Можете да се сближите доста с
git rebase --onto HEAD~4 HEAD~ master
Това предполага, че сте на master с линейна история. Това не е съвсем скуош, защото отхвърля междинните ангажименти. Ще трябва да промените новата HEAD, за да промените съобщението за ангажиране.
HEAD~4
като родител.
- person Greg Bacon; 06.09.2011