Я предлагаю вам добавить
#!/usr/bin/env python
вместо #!/usr/bin/python
в верхней части файла. Причина этого в том, что установка python может находиться в разных папках в разных дистрибутивах или на разных компьютерах. Используя env
, вы убедитесь, что система находит python и делегирует выполнение сценария.
Как уже говорилось, чтобы сделать исполняемый файл сценария, например:
chmod u+x name_of_script.py
должен делать.
Используйте git rebase -i <after-this-commit>
и замените «pick» на второй и последующие фиксации «squash» или «fixup», как описано в в руководстве .
В этом примере , <after-this-commit>
является либо хэшем SHA1, либо относительным местоположением из HEAD текущей ветви, из которого анализируются коммиты для команды rebase. Например, если пользователь хочет просмотреть 5 коммитов от текущего HEAD, команда git rebase -i HEAD~5
.
В ветке вы хотели бы объединить коммиты, запустить:
git rebase -i HEAD~(n number of commits back to review)
. Это откроет текстовый редактор, и вы должны переключить 'pick' перед каждой фиксацией на 'squash' если вы хотите, чтобы эти коммиты были объединены вместе. Например, если вы хотите объединить все коммиты в единицу, «выбрать» - это первая фиксация, которую вы сделали, и все будущие должны быть настроены на «squash». Если вы используете vim, используйте: x в режиме вставки, чтобы сохранить и выйти из редактора.
Затем, чтобы завершить rebase:
git rebase --continue
Подробнее об этом и других способах переписать история фиксации см. этот полезный пост
Просто добавьте эту функцию bash в ваш bash файла .zshrc.
# Squash last X commits with a Commit message.
# Usage: squash X 'COMMIT_MSG'
# where X= Number of last commits.
# where COMMIT_MSG= New commit msg.
function squash() {
if [ -z "${1}" -o -z "${2}" ]; then
echo "Usage: \`squash X COMMIT_MSG\`"
echo "X= Number of last commits."
echo "COMMIT_MSG= New commit msg."
return 1
fi
git reset --soft HEAD~"$1"
git add . && git ci -m "$2" # With 100 emoji
git push --force
}
Затем просто запустите
squash X 'New Commit Message'
И все готово.
Как насчет ответа на вопрос, связанный с таким рабочим процессом?
merge --squash
после PR, но команда подумала, что это замедлит процесс.) Я не видел такой рабочий процесс на этой странице. (Возможно, это мои глаза.) Если я правильно понял rebase
, для нескольких объединений потребуется несколько разрешений конфликтов. Я не хочу даже думать об этом!
Итак, это, похоже, сработает для нас.
git pull master
git checkout -b new-branch
git checkout -b new-branch-temp
git checkout new-branch
git merge --squash new-branch-temp
// помещает все изменения в стадии git commit 'one message to rule them all'
git push
Что может быть действительно удобно: найдите хеш-фиксацию, которую вы хотите сквозировать поверх; скажем, что это d43e15
Теперь используйте
git reset d43e15
git commit -am 'new commit name'
Благодаря этому удобному сообщению в блоге я обнаружил, что вы можете использовать эту команду для раздачи последних трех коммитов:
git rebase -i HEAD~3
Это удобно, поскольку это работает, даже если вы находятся в локальном филиале без информации отслеживания / удаленного репо.
Команда откроет интерактивный редактор переадресации, который затем позволит вам изменить порядок, сквош, переименование и т. д. как обычно.
Это супер-пупер kludgy, но каким-то классным способом, поэтому я просто брошу его в кольцо:
GIT_EDITOR='f() { if [ "$(basename $1)" = "git-rebase-todo" ]; then sed -i "2,\$s/pick/squash/" $1; else vim $1; fi }; f' git rebase -i foo~5 foo
Перевод: предоставить новый «редактор» для git, который , если редактируемое имя файла git-rebase-todo
(приглашение интерактивной переадресации) изменяет все, кроме первого «выбрать» на «сквош», а в противном случае порождает vim, так что когда вам будет предложено отредактировать сжатое сообщение фиксации, вы получить vim. (И, очевидно, я раздавил последние пять коммитов на ветке foo, но вы можете изменить это, как вам нравится.)
Я, вероятно, сделаю то, что предложил Марк Лонгэй .
git squash -m "New summary."
и автоматически определить N
как число нечистых коммитов.
– A-B-B
22 April 2014 в 19:50
git commit --amend
для дальнейшего изменения сообщения, но этот псевдоним позволяет вам хорошо начать то, что должно быть в сообщении фиксации.
– dashesy
14 July 2016 в 15:59
Вы можете использовать git merge --squash
для этого, что немного более элегантно, чем git rebase -i
. Предположим, что вы на хозяине, и вы хотите раздавить последние 12 коммитов в одном.
ВНИМАНИЕ: сначала убедитесь, что вы совершили проверку работоспособности, что git status
чиста (поскольку git reset --hard
выбрасывает поэтапные и неустановленные изменения)
Затем:
# Reset the current branch to the commit just before the last 12:
git reset --hard HEAD~12
# HEAD@{1} is where the branch was just before the previous command.
# This command sets the state of the index to be as it would just
# after a merge from that commit:
git merge --squash HEAD@{1}
# Commit those squashed changes. The commit message will be helpfully
# prepopulated with the commit messages of all the squashed commits:
git commit
Документация для git merge
более подробно описывает параметр --squash
.
Обновление: единственное реальное преимущество этого метода по сравнению с более простым git reset --soft HEAD~12 && git commit
, предложенным Крисом Джонсеном в , его ответом является то, что вы получаете сообщение о фиксации preopulated с каждым сообщением фиксации, которое вы раздавите.
git rebase -i
, но вы не даете причины. Ориентировочно это, потому что мне кажется, что на самом деле обратное верно, и это взломать; вы не выполняете больше команд, чем необходимо, только для того, чтобы заставить git merge
делать одно из того, что специально предназначено для git rebase
?
– Mark Amery
8 July 2013 в 12:14
git merge --squash
также проще в использовании в скрипте. По существу, рассуждение состояло в том, что вам не нужна «интерактивность». из git rebase -i
вообще для этого.
– Mark Longair
8 July 2013 в 16:59
git merge --squash
с меньшей вероятностью создает конфликты слияния при перемещении / удалении / переименованиях по сравнению с rebasing, особенно если вы сливаетесь из локальной ветви. (отказ от ответственности: основываясь только на одном опыте, исправьте меня, если это не так в общем случае!)
– Cheezmeister
28 February 2014 в 00:21
HEAD@{1}
, чтобы быть в безопасности, например. когда ваш рабочий процесс прерывается в течение часа при отключении питания и т. д.
– Tobias Kienzler
11 August 2014 в 13:18
Я нахожу, что более общим решением является не указание «N» коммитов, а скорее идентификатор ветки / фиксации, который вы хотите раздавить поверх. Это менее подвержено ошибкам, чем подсчет коммиттов до определенного коммита - просто укажите тег напрямую или если вы действительно хотите подсчитать, вы можете указать HEAD ~ N.
В моем рабочем процессе я запускаю ветви, и моя первая фиксация на этой ветке суммирует цель (т.е. обычно это то, что я буду нажимать как «окончательное» сообщение для этой функции в публичный репозиторий.) Поэтому, когда я закончил, все, что я хочу сделать, это git squash master
назад к первому сообщению, а затем я готов нажать.
Я использую псевдоним:
squash = !EDITOR="\"_() { sed -n 's/^pick //p' \"\\$1\"; sed -i .tmp '2,\\$s/^pick/f/' \"\\$1\"; }; _\"" git rebase -i
Это сбрасывает историю, раздавленную до того, как она это сделает - это дает вам возможность восстановиться, захватив старый идентификатор фиксации с консоли, если вы хотите вернуться. (Пользователи Solaris отмечают, что используют параметр GNU sed -i
, пользователи Mac и Linux должны быть в порядке с этим.)
git squash master
, когда мы проверяем ведомое устройство. что это будет? скроем конфликт?
– Sergio Bilello
24 February 2016 в 08:55
В дополнение к другим отличным ответам я хотел бы добавить, как git rebase -i
всегда путает меня с порядком фиксации - от старого до более нового или наоборот? Итак, это мой рабочий процесс:
git rebase -i HEAD~[N]
, где N - число коммитов, которые я хочу присоединиться, , начиная с самого последнего . Таким образом, git rebase -i HEAD~5
будет означать «squash последние 5 коммитов в новый»; Вы можете сделать это довольно легко без git rebase
или git merge --squash
. В этом примере мы раздавим последние 3 коммита.
Если вы хотите записать новое сообщение о фиксации с нуля, это достаточно:
git reset --soft HEAD~3 &&
git commit
Если вы хотите начать редактируя новое сообщение фиксации с помощью конкатенации существующих сообщений фиксации (т. е. похоже на то, что будет запускать список инструкций pick / squash / squash / ... / squash git rebase -i
), тогда вам нужно извлечь эти сообщения и передать их git commit
:
git reset --soft HEAD~3 &&
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"
Оба этих метода скворуют последние три коммита в один новый коммит таким же образом. Мягкий сброс просто перенаправляет HEAD на последнюю фиксацию, которую вы не хотите раздавить. Ни индекс, ни рабочее дерево не касаются мягкого сброса, оставляя индекс в желаемом состоянии для вашего нового коммита (т. Е. Он уже имеет все изменения от коммитов, которые вы собираетесь «выбросить»).
git rebase --squash-recent
или даже git commit --amend-many
.
– Adrian Ratnapala
8 November 2013 в 19:50
branch@{upstream}
(или только @{upstream}
для текущей ветви; в обоих случаях последняя часть может быть сокращена до @{u}
; [д0] gitrevisions [/ д0]). Это может отличаться от вашего i> "последнего нажатого фиксации" (например, если кто-то другой нажал что-то, что было создано на вашем последнем нажатии, а затем вы его выбрали), но похоже, что он может быть близок к тому, что вы хотите.
– Chris Johnsen
23 April 2014 в 07:13
push -f
, но в остальном это было прекрасно, спасибо.
– 2rs2ts
30 October 2014 в 00:32
Для этого вы можете использовать следующую команду git.
git rebase -i HEAD~n
n (= 4 здесь) - это номер последней фиксации. Затем вы получите следующие опции:
pick 01d1124 Message....
pick 6340aaa Message....
pick ebfd367 Message....
pick 30e0ccb Message....
Обновить, как показано ниже,
p 01d1124 Message....
s 6340aaa Message....
s ebfd367 Message....
s 30e0ccb Message....
Удачи !!
Другой способ сделать это, если у вас есть тонна коммитов, - сделать сквош ПОСЛЕ фиксации, как git rebase -i <hashbeforeyouwanttosquash>
. Это откроет ваш редактор, чтобы выбрать / сквош, как обычно.
Взгляните на этот смысл:
Вам нужно будет ввести, например. git-squash 3
и все. Последние три коммита объединяются в один с конкатенированными сообщениями.
Переключитесь на главную ветку и убедитесь, что вы в курсе:
sh
git checkout master && git fetch && git pull
Объедините ветвь вашей функции в ведущую ветвь локально:
sh
git merge feature_branch
Сбросить локальную ведущую ветвь в состояние начала:
sh
git reset origin/master
Теперь все ваши изменения считаются неустановленными. Вы можете выполнить и передать их в одну или несколько коммитов.
sh
git add . --all
git commit
В вопросе может быть неоднозначным, что подразумевается под «последним».
, например git log --graph
выводит следующее (упрощенное):
* commit H0
|
* merge
|\
| * commit B0
| |
| * commit B1
| |
* | commit H1
| |
* | commit H2
|/
|
. Затем последние фиксируются по времени: H0, merge, B0.
Проблема заключается в том, что H0 содержит H1 и H2 (и, как правило, больше коммитов перед слиянием и после ветвления), а B0 - нет. Таким образом, вам нужно управлять изменениями от H0, merge, H1, H2, B0 по крайней мере.
Можно использовать rebase, но по-другому, а затем в других упомянутых ответах:
rebase -i HEAD~2
Это покажет вам варианты выбора (как упоминалось в других ответах):
pick B1
pick B0
pick H0
Поместите сквош вместо выбора в H0:
pick B1
pick B0
s H0
После сохранения и выключения rebase будет применяться фиксация по очереди после H1. Это означает, что он попросит вас снова разрешить конфликты (где HEAD будет сначала H1, а затем накапливает фиксации по мере их применения).
После того, как rebase завершится, вы можете выбрать сообщение для раздавленных H0 и B0:
* commit squashed H0 and B0
|
* commit B1
|
* commit H1
|
* commit H2
|
PS Если вы просто выполните сброс в BO: (например, используя reset --mixed
, который более подробно объясняется здесь https://stackoverflow.com/a/18690845/2405850 ):
git reset --mixed hash_of_commit_B0
git add .
git commit -m 'some commit message'
, тогда вы раздавите в B0 изменения H0, H1, H2 (потеря полностью фиксирует изменения после разветвления и перед слиянием.
Если вы находитесь на удаленной ветке (называемой feature-branch
), клонированной из Золотого репозитория (golden_repo_name
), то вот техника, чтобы раздавить ваши коммиты в одну:
git checkout golden_repo_name
git checkout -b dev-branch
git merge --squash feature-branch
git commit -m "My feature complete"
git push origin dev-branch
Ответ аномии хорош, но я чувствовал себя неуверенно в этом, поэтому решил добавить пару скриншотов.
Посмотрите, где вы находитесь git log
. Самое главное, найдите хеш фиксации первой фиксации, которую вы не хотите , чтобы сквош. Таким образом, только:
Выполнить git rebase -i [your hash]
, в мой случай:
$ git rebase -i 2d23ea524936e612fae1ac63c95b705db44d937d
В моем случае я хочу раздавить все на коммит, который был первым во времени. Порядок от первого до последнего, так точно так же, как в git log
. В моем случае я хочу:
Если вы выбрали только одно коммит и раздавили остальное, вы можете настроить одно сообщение фиксации:
Вот и все. Как только вы сохраните это (:wq
), все готово. Посмотрите на это с помощью git log
.
Если вы используете TortoiseGit, вы можете использовать функцию Combine to one commit
:
Я рекомендую избегать git reset
, когда это возможно, особенно для Git-новичков. Если вам действительно не нужно автоматизировать процесс, основанный на числе коммитов, существует менее экзотический способ ...
git merge --squash (working branch name)
git commit
Сообщение фиксации будет предварительно заполнено на основе сквоша.
gitk
должен обозначать строку кода, который вы раздавите, а также наклейте базу, на которую нужно сквозировать. В нормальном случае обе эти метки уже существуют, поэтому шаг (1) можно пропустить.
– nobar
11 April 2017 в 21:48
git branch your-feature && git reset --hard HEAD~N
наиболее удобный способ. Однако он снова включает сброс git, который этот ответ пытался избежать.
– eis
30 May 2017 в 17:01
1) Определите короткую хэш-запись фиксации
# git log --pretty=oneline --abbrev-commit
abcd1234 Update to Fix for issue B
cdababcd Fix issue B
deab3412 Fix issue A
....
2) Если вы хотите скворовать (объединить) последние две фиксации
# git rebase -i deab3412
3) Это открывает кнопку nano
для слияния. И это выглядит ниже
....
pick cdababcd Fix issue B
pick abcd1234 Update to Fix for issue B
....
4) Переименуйте слово pick
в squash
, которое присутствует перед abcd1234
. После переименования он должен выглядеть следующим образом.
....
pick cdababcd Fix issue B
squash abcd1234 Update to Fix for issue B
....
5) Теперь сохраните и закройте редактор nano
. Нажмите ctrl + o
и нажмите Enter
для сохранения. И затем нажмите ctrl + x
, чтобы выйти из редактора.
6) Затем редактор nano
снова открывается для обновления комментариев, при необходимости обновляет его.
7) Теперь его сжатие успешно, вы можете проверить его, проверив журналы.
# git log --pretty=oneline --abbrev-commit
1122abcd Fix issue B
deab3412 Fix issue A
....
8) Теперь нажмите на репо. Примечание, чтобы добавить знак +
перед именем ветки.
# git push origin +master
Примечание. Это основано на использовании git на оболочке ubuntu
. Если вы используете разные os (Windows
или Mac
), то выше команды такие же, кроме редактора. Вы можете получить другой редактор.
Если вы используете GitUp , выберите фиксацию, которую хотите объединить с ее родителем, и нажмите S. Вы должны сделать это один раз для каждой фиксации, но это намного проще, чем придумать правильное заклинание командной строки. Особенно, если это то, что вы делаете только время от времени.
Основываясь на этой статье , я нашел этот метод более удобным для моей usecase.
. Моя ветка «dev» опередила «origin / dev» на 96 коммитов (так что эти коммиты еще не были отодвинуты на пульт).
Я хотел пробить эти коммиты в один, прежде чем нажимать изменение. Я предпочитаю переустановить ветвь в состояние «origin / dev» (это оставит все изменения с 96 фиксированными неустановленными), а затем зафиксирует изменения сразу:
git reset origin/dev
git add --all
git commit -m 'my commit message'
Я думаю, что самый простой способ сделать это - сделать новую ветку от мастера и выполнить слияние --squash ветки функции.
git checkout master
git checkout -b feature_branch_squashed
git merge --squash feature_branch
Тогда у вас есть все изменения, готовые для фиксации.
Если вы хотите хлюпить каждый совершить в одном коммите (например, при первом выпуске проекта в первый раз), попробуйте:
git checkout --orphan <new-branch>
git commit
git rebase -i HEAD^^
, где число ^ равно X
(в этом случае сквош две последние коммиты)
<after-this-commit>
? – jtheletter 4 November 2014 в 06:49<after-this-commit>
является фиксацией X + 1, то есть родительской старейшей фиксации, которую вы хотите сквош. – joozek 4 November 2014 в 13:04rebase -i
иreset --soft
равнаrebase -i
, позволяет мне сохранить автора фиксации, аreset --soft
позволяет мне повторно подтвердить. Иногда мне нужно выполнять сквош-фиксацию запросов на тягу, сохраняя при этом информацию об авторе. Иногда мне нужно сбросить софт самостоятельно. В любом случае, это оправдывает оба больших ответа. – zionyx 15 September 2015 в 09:31