#git #bitbucket #git_commit #git_push
Дано: Последовательные коммиты А и В, запушенные в удалённый репозиторий. Задача: Сделать из них один коммит С. Вопрос: Беглое гугленье убеждает меня в том, что достаточно что-то типа такого сделать: git squash А git squash В git push origin branchname Верно ли я понял и что в процессе может пойти не так?
Ответы
Ответ 1
Шаг 0: а можно ли это делать? что в процессе может пойти не так Если коммиты последовательные, то конфликтов изменений не будет. Но поскольку коммиты уже отправлены на удалённый репозиторий, то вам придётся переписывать историю там и что-нибудь может пойти не так у коллег. Вот пара вопросов о том, что и когда можно ребейзить и переписывать: В каких случаях rebase можно и нужно делать, а в каких нет? Откатить уже опубликованный коммит и опубликовать новый, не вызывая мержа у других Кратко: никогда нельзя это делать в стабильных ветках репозитория, где кроме вас есть ещё хоть один разработчик. Шаг 1а: сплющивание через rebase -i Под git squash вы наверное понимаете git rebase --interactive с последующим выбором опции squash. Действительно, можно сделать так: Ребейз к третьему коммиту с конца (пред-предпоследнему) git rebase -i HEAD^^ откроется такой документ: pick 7423f96 сообщение предпоследнего коммита pick 91e9b6e сообщение последнего коммита # Rebase c9e8f38..91e9b6e onto c9e8f38 (2 commands) ... Чтобы объединить два коммита в один нужно сделать squash последнего в предпоследний: pick 7423f96 сообщение предпоследнего коммита squash 91e9b6e сообщение последнего коммита А потом сохранить документ и выйти из редактора. Откроется новый документ, в котором можно написать сообщение для вновь полученного коммита. По умолчанию там будет: # This is a combination of 2 commits. # This is the 1st commit message: сообщение предпоследнего коммита # This is the commit message #2: сообщение последнего коммита Закомментированные строки не войдут в сообщение. Если оставить пустую строку, то rebase будет прерван. Шаг 1б: сплющивание через reset Поскольку нужно объединить N последних коммитов, отлично подойдёт более простой способ: # сначала очистим индекс (staging area, область подготовки коммита), # чтобы потом не закоммитить ничего лишнего git reset . # поехали git reset --soft HEAD^^ Произошло следующее: текущая ветка переставлена на коммит HEAD^^, т.е. на два коммита назад. изменения всех коммитов вплоть до, но не включая HEAD^^ собраны в индекс Можно сделать новый коммит: git commit -m'message' В отличие от способа с rebase, информация об авторе и дате оригинального коммита не сохраняется. Лучше не ребейзить таким образом чужие коммиты, т.к. информация об авторстве обычно важна. Шаг 1в: комбинированный подход Предположим, что в предпоследнем коммите у вас написано нормальное сообщение, раскрывающее суть изменений. А в последнем вы исправили опечатку. Т.е. было бы удобно объединить два коммита, оставив сообщение от предпоследнего. # То же, что и в шаге 1б: собираем содержимое последнего коммита в индекс git reset . git reset --soft HEAD^ # "редактируем" последний коммит, добавляя в него содержимое индекса # (на самом деле создаём новый коммит с тем же сообщением и переставляем на него ветку) git commit --amend --no-edit Шаг 2. запушить на удалённый репозиторий Поскольку вы переписали свою ветку, нужно будет запушить с -f. git push -f origin mybranchОтвет 2
Я бы сделал так: git reset --soft HEAD~2 git commit git push -f origin Всё это, разумеется, если у Вас коммиты на конце текущей ветви. В противном случае придётся делать rebase.Ответ 3
Нет такой команды как git squash, делайте через git rebase -i. $ git squash git: 'squash' is not a git command. See 'git --help'. Did you mean this? stash $ git --version git version 1.8.3.1 Вот тут ещё советуют создать алиас на squash. Проблем со сплющиванием двух последовательных коммитов не будет. :сли вам нужно влить B в A, то проблем не возникнет. (Так же как и при вливании N последовательных коммитов в предыдущий). Сложности могут возникнуть в том случае, если между A и B есть другие коммиты. В общем случае если нужно влить B в A - делайте так. (переключаемся на нужную ветку) $ git rebase -i HEAD~4 pick 8394e5a commit pick 33b90d9 A pick 5c633cf B pick 1604c23 yet another commit # Rebase 76e6ae0..1604c23 onto 76e6ae0 # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out ~ "~/ansible/test/.git/rebase-merge/git-rebase-todo" 22L, 780C Приводите к виду: pick 8394e5a commit pick 33b90d9 A s 5c633cf B pick 1604c23 yet another commit Далее выходите с сохранением и пушим изменения в удалённую ветку. Как обычно: не забываем, что изменение истории через rebase требует git push -f, что в общем случае не приветствуется в командной работе.
Комментариев нет:
Отправить комментарий