How to squash commits git
How to squash commits git
Как сжимать коммиты в Git с помощью git squash
Git squash — это прием, который помогает взять серию коммитов и уплотнить ее. Например, предположим: у вас есть серия из N коммитов и вы можете путем сжатия преобразовать ее в один-единственный коммит. Сжатие через git squash в основном применяется, чтобы превратить большое число малозначимых коммитов в небольшое число значимых. Так становится легче отслеживать историю Git.
Также этот прием используется при объединении ветвей. Чаще всего вам будут советовать всегда сжимать коммиты и выполнять перебазирование с родительской ветвью (например, master или develop ). В таком случае история главной ветки будет содержать только значимые коммиты, без ненужной детализации.
Как именно делать git squash
Возьмем для примера следующую историю Git:
Здесь видны последние три коммита. В сообщениях к ним поясняется, что мы добавили новый файл и какое-то содержимое. Лучше заменить их одним единственным коммитом о том, что произошло добавление нового файла с некоторым содержимым. Итак, давайте посмотрим, как сжать последние три коммита в один:
3 означает, что мы берем последние три коммита.
Здесь изменилось сообщение о коммите, и обратите внимание: три коммита “склеились” в один. Также изменился хэш коммита. Через git rebase всегда создается новый коммит, содержащий соответствующие изменения.
Так что используйте этот инструмент с осторожностью.
Помните: сжатие коммитов меняет историю Git, поэтому не рекомендуется сжимать ветвь, если вы уже отправили ее в удаленный репозиторий. Всегда выполняйте сжатие до того, как отправить пуш с изменениями.
Применение fixup для сжатия коммитов
Обратите внимание: хэш коммита также изменился, а сообщение о коммите берется из “основного” коммита, с которым были сжаты другие два.
Применение сжатия при слиянии ветвей
Git также предоставляет возможность сжатия при объединении ветвей. Во многих случаях она может оказаться полезной. Чтобы добавить новый функционал или поправить какие-то баги, нам понадобится то и дело что-то изменять в ветвях. Поэтому, когда мы будем готовы слить эти изменения в основную ветвь ( master или develop ), для начала следует применить сжатие.
Давайте рассмотрим следующую команду:
Она берет все коммиты из целевой ветви, сжимает их и сохраняет все изменения в текущей ветви. Затем вы можете зафиксировать все изменения в одном коммите. На примере это выглядит так:
Сжатие коммитов через Github
Возможность сжимать коммиты предоставляет и Github. Эта функция особенно полезна при пулл-реквесте.
Сначала производится сжатие, затем — слияние. Так что вместо пяти коммитов получится один.
Как видно на картинке, выполняется всего один коммит с соответствующим сообщением.
Спасибо за чтение! Надеюсь, вы почерпнули из статьи что-то новое 🙂
Как склеить коммиты и зачем это нужно
Другие материалы по Git
Когда вы открываете пулреквест, и ваш код смотрят и комментируют другие, бывает нужно что-то исправить. Обычно такие изменения мы комментируем сообщением вроде «Увеличил шрифт на 2px» или «Поменял оттенок фона в шапке». Такие маленькие изменения интересны только пока они в пулреквесте. Ревьювер (человек, который смотрит ваш код), может легко узнать, что и когда вы изменили, а не читать весь diff заново, а вы можете легко откатить коммит, если он не нужен. Но когда приходит время вливать пулреквест, эти маленькие коммиты теряют свою ценность. Поэтому лучше их склеить в один. Как — я расскажу вам сегодня.
Как подготовиться
Для некоторых операций из этой статьи гит будет открывать текстовый редактор. Во многих системах по умолчанию это Vim. Не самый дружелюбный для новичков. Чтобы вам было комфортно, установите в качестве гит-редактора ваш любимый редактор. Это делается с помощью команды:
Например, если у вас Mac OS, и вы хотите установить Atom в качестве редактора по умолчанию, введите:
А если у вас Windows, и вы хотите установить Notepad++ в качестве гит-редактора, ваша команда будет такая:
Вам нужно просто узнать команду для запуска вашего редактора и подставить её. Вот список команд для популярных редакторов.
Git — инструмент фронтендера
Пройдите обучение в HTML Academy, чтобы работать с системами контроля версий и другими инструментами как профессионал.
Как склеивать коммиты
Сначала узнаем, сколько коммитов нужно склеить. Эта команда покажет, какие коммиты у вас прибавились по сравнению с веткой master:
А эта — сколько их:
Отлично, у меня 5 коммитов. Теперь я хочу переписать историю с момента HEAD
Тут список моих коммитов и большой комментарий о том, что я могу сделать. Из списка комманд видно, что мы можем использовать squash или fixup для того, чтобы склеить коммиты. Первый пригодится тогда, когда вы хотите изменить коммит-месседж, а второй — когда хотите использовать коммит-месседж первого. Итак, чтобы склеить все коммиты, я делаю вот так:
Сквош коммитов
То есть я говорю гиту «используй первый коммит, а остальные приклей к нему». Потом я сохраняю файл и закрываю его. Гит склеивает коммиты и предлагает мне ввести коммит-месседж (показывает коммит-месседжи всех склеенных коммитов):
Коммит-месседжи склеенных коммитов
Я хочу оставить только последний:
Коммит-месседж результирующего коммита
Сохраняю файл и смотрю лог:
git log
Ура, остался один коммит с нужным сообщением.
git push
Теперь всё получилось! Используйте форс только тогда, когда вы уверены в своих действиях!
Как автоматизировать ребейз
Обычно всё-таки нужно оставить коммит-месседж первого изменения, типа «Сверстал то-то», остальные коммиты — просто правки к нему. Число правок иногда доходит до 15, не очень удобно сидеть и писать везде squash. Можно сделать так, чтобы коммиты автоматически присквошивались к нужному, только для этого нужно их правильно коммитить. Предположим, вы поменяли файл и хотите закоммитить изменения как правку по ревью:
git status
Сначала надо узнать хеш коммита, к которому этот коммит является правкой. Воспользуемся уже знакомым cherry :
Ага, вот он наш хеш. А теперь следующий коммит обозначим правкой к этому:
Необязательно в точности копировать весь хеш, достаточно первых 7 символов. Я обычно выделяю от начала и сколько выделится и копирую:
git log
Добавим ещё несколько правок таким образом. Посмотрим изменения:
Отлично. А теперь склеим все эти коммиты. Только не вручную. Гит сделает это за нас:
И гит сам подставит слово fixup там, где нужно:
Просто сохраняем, и гит склеивает коммиты и использует коммит-месседж первого:
Результат автосквоша
How to squash commits in git after they have been pushed?
This gives a good explanation of squashing multiple commits:
but it does not work for commits that have already been pushed. How do I squash the most recent few commits both in my local and remote repos?
10 Answers 10
Trending sort
Trending sort is based off of the default sorting method — by highest score — but it boosts votes that have happened recently, helping to surface more up-to-date answers.
It falls back to sorting by highest score if no posts are trending.
Switch to Trending sort
Squash commits locally with
and then force push with
From the documentation of git push :
On a branch I was able to do it like this (for the last 4 commits)
Minor difference to accepted answer, but I was having a lot of difficulty squashing and finally got it.
Push to the remote using:
A lot of problems can be avoided by only creating a branch to work on & not working on master :
The following works for remote commits already pushed & a mixture of remote pushed commits / local only commits:
I also have some pull request notes which may be helpful.
you will get the editor vm open and msgs something like this
Here I have changed pick for all the other commits to «f» (Stands for fixup).
To elaborate: It works on the current branch; the HEAD
4 means squashing the latest four commits; interactive mode (-i)
2) At this point, the editor opened, with the list of commits, to change the second and following commits, replacing pick with squash then save it.
output: Successfully rebased and updated refs/heads/branch-name.
For squashing two commits, one of which was already pushed, on a single branch the following worked:
By default, this will include the commit message of the newest commit as a comment on the older commit.
When you are working with a Gitlab or Github you can run in trouble in this way. You squash your commits with one of the above method. My preferite one is:
select squash or fixup for yours commit. At this point you would check with git status. And the message could be:
And you can be tempted to pull it. DO NOT DO THAT or you will be in the same situation as before.
Instead push to your origin with:
The + allow to force push only to one branch.
Sqush Changes in remote
In my case requirement was to squash all the feature branch commits into one, to have a clean commit history. Utilized the GitHub UI to do so.
12 commits, a month of work). And has been pushed to remote regularly.
Now the featureBranchLatest will have a single commit of all the changes needed in a single commit, along with the latest changes from the master. Delete the old branch featureBranch if not required for reference.
patik / how-to-squash-commits-in-git.md
Squashing Git Commits
The easy and flexible way
This method avoids merge conflicts if you have periodically pulled master into your branch. It also gives you the opportunity to squash into more than 1 commit, or to re-arrange your code into completely different commits (e.g. if you ended up working on three different features but the commits were not consecutive).
Note: You cannot use this method if you intend to open a pull request to merge your feature branch. This method requires committing directly to master.
Switch to the master branch and make sure you are up to date:
Merge your feature branch into the master branch locally:
Reset the local master branch to origin’s state:
Now all of your changes are considered as unstaged changed. You can stage and commit them into one or more commits.
The hard(er) and less flexible way
This method only allows you to squash the last X consecutive commits into a single commit. Also, if you have merged master into your branch along the way, you will have to manually merge your new (squashed) commit into master and resolve the merge conflicts.
Use this method if you have not merged master into your branch, you plan to combine all commits into one, and you only changed one feature of the project; or, regardless of those conditions, you must use this method if you intend to open a pull request to merge your code.
Combining the commits
To squash the last 3 commits into one:
Pushing the squashed commit
If the commits have been pushed to the remote:
The plus sign forces the remote branch to accept your rewritten history, otherwise you will end up with divergent branches
If the commits have NOT yet been pushed to the remote:
In other words, just a normal push like any other
ghost commented Sep 26, 2017
git checkout master && git fetch && git pull
git pull is a synonym for git fetch && git merge so your version will git fetch twice, although the second time it likely won’t fetch anything, so it probably doesn’t matter.
git merge feature_branch
I think you are better to
The reason I say that is because if you’ve merged your feature_branch to your local master, how do you then push it to origin master with an opportunity for someone else to review & merge your commit? I don’t think you can create a pull request from your local to a remote, only push directly,
Although, workflows in git differ, so this might work for you if no-one is reviewing the code and you are happy to just push direct to origin/master. If that’s the case, creating branches is more of a convenience for working on multiple discrete changes and being able to switch between them cleanly.
Git: How to squash all commits on branch
I make new branch from master with:
I make 20 commits into it.
Now I want to squash those 20 commits. I do that with:
What about if I don’t know how many commits? Is there any way to do something like:
18 Answers 18
Trending sort
Trending sort is based off of the default sorting method — by highest score — but it boosts votes that have happened recently, helping to surface more up-to-date answers.
It falls back to sorting by highest score if no posts are trending.
Switch to Trending sort
Another way to squash all your commits is to reset the index to master:
This isn’t perfect as it implies you know from which branch «yourBranch» is coming from.
Note: finding that origin branch isn’t easy/possible with Git (the visual way is often the easiest, as seen here).
[That] automatically uses the branch you are currently on.
And if you use that, you can also use an alias, as the command doesn’t rely on the branch name.
Since my default branch is called main and my search had multi times brought me here:
To copy it for my next time
Step 1:
Step 2:
Add all of the changes in your git repo directory, to the new commit that is going to be created. And commit the same with a message.
What you’re doing is pretty error-prone. Just do:
which will automatically rebase only your branch’s commits onto the current latest master.
Assuming you were branching from the master, you don’t need to enter yourBranch into the reset step all the time:
Explanation:
20 will make a soft reset of the last 20 commits. This leaves your changes in the files, but removes the commits.
Usage:
Hint:
If you’re using Gitlab >= 11.0 you don’t need to do this anymore as it has a squashing option when merging branches.
Based on reading several Stackoverflow questions and answers on squashing, I think this is a good one liner to squash all commits on a branch:
This is assuming master is the base branch.
Solution for people who prefer clicking:
Install sourcetree (it is free)
Check how your commits look like. Most likely you have something similar to this
Right click on parent commit. In our case it is master branch.
You can squash commit with previous one by clicking a button. In our case we have to click 2 times. You can also change commit message
Results are awesome and we are ready to push!
Side note: If you were pushing your partial commits to remote you have to use force push after squash
Since I had some trouble with the solutions proposed here, I want to share a really simple solution (which really works regardless):
A. Pull master into your feature branch (Make sure to update your Master)
B. Do soft reset to master
C. Commit your changes
Squashing Commit using git rebase
A.
B. You will get one interactive prompt where you need to Pick the top commit and insert squash or s in front of those which you want to combine/squash.
Note: Make sure do changes in insert mode and save the file ; (wq in VI Editor)
C. Now you will get another interactive prompt where you need to put # in front of commits message that you don’t want, and or add your own message. Again save the file and your commits will successfully rebase.
You need to get the merge base of your branch
Then you can rebase to it
or just do a soft-reset and commit everything
Automate
and then do these directly in the terminal.
but if you’re merging against a different branch than master then you can replace master with «$1» to do this
If you use JetBrains based IDE like IntelliJ Idea and prefare using GUI over command line:
That’s it. You uncommited all your changes. Now if you’ll make a new commit it will be squashed
You can do this with subcommands ie
This will run first count the commits since you diverged from master and then rebase back to that exact length.
You can use tool I’ve created specifically for this task:
Basically you need to call git squash master and you’re done
Another solution would be to save all commit logs to a file
git log > branch.log
Now branch.log will have all commit ids since beginning.. scroll down and take the first commit (this will be difficult in terminal) using the first commit
all commits will be squashed
Git reset, as mentioned in many answers before, is by far the best and simplest way to achieve what you want. I use it in the following workflow:
(on development branch)
Saved my life, and will be my go to squash, been using this 4 times since I found out about it. Simple, clean and basically 1 comamnd. In short:
If you are on a branch lets call it «my_new_feature» off develop and your pull request has 35 commits (or however many) and you want it to be 1.
A. Make sure your branch is up to date, Go on develop, get latest and merge and resolve any conflicts with «my_new_feature»
(this step really you should take as soon as you can all the time anyway)
B. Get latest of develop and branch out to a new branch call it «my_new_feature_squashed»
Источники информации:
- http://htmlacademy.ru/blog/best/how-to-squash-commits-and-why-it-is-needed
- http://stackoverflow.com/questions/5667884/how-to-squash-commits-in-git-after-they-have-been-pushed
- http://gist.github.com/patik/b8a9dc5cd356f9f6f980
- http://stackoverflow.com/questions/25356810/git-how-to-squash-all-commits-on-branch