(window.webpackJsonp=window.webpackJsonp||[]).push([[1151],{1560:function(t,e,s){"use strict";s.r(e);var a=s(31),o=Object(a.a)({},(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"squashing"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#squashing"}},[t._v("#")]),t._v(" Squashing")]),t._v(" "),s("h2",{attrs:{id:"squash-recent-commits-without-rebasing"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#squash-recent-commits-without-rebasing"}},[t._v("#")]),t._v(" Squash Recent Commits Without Rebasing")]),t._v(" "),s("p",[t._v("If you want to squash the previous "),s("code",[t._v("x")]),t._v(" commits into a single one, you can use the following commands:")]),t._v(" "),s("div",{staticClass:"language-git extra-class"},[s("pre",{pre:!0,attrs:{class:"language-git"}},[s("code",[t._v("git reset --soft HEAD~x\ngit commit\n\n")])])]),s("p",[t._v("Replacing "),s("code",[t._v("x")]),t._v(" with the number of previous commits you want to be included in the squashed commit.")]),t._v(" "),s("p",[t._v("Mind that this will create a "),s("strong",[t._v("new")]),t._v(" commit, essentially forgetting information about the previous "),s("code",[t._v("x")]),t._v(" commits including their author, message and date. You probably want to "),s("strong",[t._v("first")]),t._v(" copy-paste an existing commit message.")]),t._v(" "),s("h2",{attrs:{id:"squashing-commits-during-a-rebase"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#squashing-commits-during-a-rebase"}},[t._v("#")]),t._v(" Squashing Commits During a Rebase")]),t._v(" "),s("p",[t._v("Commits can be squashed during a "),s("code",[t._v("git rebase")]),t._v(". It is recommended that you understand "),s("a",{attrs:{href:"http://stackoverflow.com/documentation/git/355/rebasing#t=201604292236379558058",target:"_blank",rel:"noopener noreferrer"}},[t._v("rebasing"),s("OutboundLink")],1),t._v(" before attempting to squash commits in this fashion.")]),t._v(" "),s("li",[t._v("\nDetermine which commit you would like to rebase from, and note its commit hash.\n")]),t._v(" "),s("li",[t._v("\nRun `git rebase -i [commit hash]`.\nAlternatively, you can type `HEAD~4` instead of a commit hash, to view the latest commit and 4 more commits before the latest one.\n")]),t._v(" "),s("li",[t._v("\nIn the editor that opens when running this command, determine which commits you want to squash. Replace `pick` at the beginning of those lines with `squash` to squash them into the previous commit.\n")]),t._v(" "),s("li",[t._v("\nAfter selecting which commits you would like to squash, you will be prompted to write a commit message.\n")]),t._v(" "),s("p",[t._v("Logging Commits to determine where to rebase")]),t._v(" "),s("div",{staticClass:"language-git extra-class"},[s("pre",{pre:!0,attrs:{class:"language-git"}},[s("code",[t._v("> git log --oneline\n612f2f7 This commit should not be squashed\nd84b05d This commit should be squashed\nac60234 Yet another commit\n36d15de Rebase from here\n17692d1 Did some more stuff\ne647334 Another Commit\n2e30df6 Initial commit\n\n> git rebase -i 36d15de\n\n")])])]),s("p",[t._v("At this point your editor of choice pops up where you can describe what you want to do with the commits. Git provides help in the comments. If you leave it as is then nothing will happen because every commit will be kept and their order will be the same as they were before the rebase. In this example we apply the following commands:")]),t._v(" "),s("div",{staticClass:"language-git extra-class"},[s("pre",{pre:!0,attrs:{class:"language-git"}},[s("code",[t._v("pick ac60234 Yet another commit\nsquash d84b05d This commit should be squashed\npick 612f2f7 This commit should not be squashed\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Rebase 36d15de..612f2f7 onto 36d15de (3 command(s))")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("#")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Commands:")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# p, pick = use commit")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# r, reword = use commit, but edit the commit message")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# e, edit = use commit, but stop for amending")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# s, squash = use commit, but meld into previous commit")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('# f, fixup = like "squash", but discard this commit\'s log message')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# x, exec = run command (the rest of the line) using shell")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("#")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# These lines can be re-ordered; they are executed from top to bottom.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("#")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# If you remove a line here THAT COMMIT WILL BE LOST.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("#")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# However, if you remove everything, the rebase will be aborted.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("#")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Note that empty commits are commented out")]),t._v("\n\n")])])]),s("p",[t._v("Git log after writing commit message")]),t._v(" "),s("div",{staticClass:"language-git extra-class"},[s("pre",{pre:!0,attrs:{class:"language-git"}},[s("code",[t._v("> git log --oneline\n77393eb This commit should not be squashed\ne090a8c Yet another commit\n36d15de Rebase from here\n17692d1 Did some more stuff\ne647334 Another Commit\n2e30df6 Initial commit\n\n")])])]),s("h2",{attrs:{id:"squashing-commit-during-merge"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#squashing-commit-during-merge"}},[t._v("#")]),t._v(" Squashing Commit During Merge")]),t._v(" "),s("p",[t._v("You can use "),s("code",[t._v("git merge --squash")]),t._v(" to squash changes introduced by a branch into a single commit. No actual commit will be created.")]),t._v(" "),s("div",{staticClass:"language-git extra-class"},[s("pre",{pre:!0,attrs:{class:"language-git"}},[s("code",[t._v("git merge --squash \ngit commit\n\n")])])]),s("p",[t._v("This is more or less equivalent to using "),s("code",[t._v("git reset")]),t._v(", but is more convenient when changes being incorporated have a symbolic name. Compare:")]),t._v(" "),s("div",{staticClass:"language-git extra-class"},[s("pre",{pre:!0,attrs:{class:"language-git"}},[s("code",[t._v("git checkout \ngit reset --soft $(git merge-base master )\ngit commit\n\n")])])]),s("h2",{attrs:{id:"autosquash-committing-code-you-want-to-squash-during-a-rebase"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#autosquash-committing-code-you-want-to-squash-during-a-rebase"}},[t._v("#")]),t._v(" Autosquash: Committing code you want to squash during a rebase")]),t._v(" "),s("p",[t._v("Given the following history, imagine you make a change that you want to squash into the commit "),s("code",[t._v("bbb2222 A second commit")]),t._v(":")]),t._v(" "),s("div",{staticClass:"language-git extra-class"},[s("pre",{pre:!0,attrs:{class:"language-git"}},[s("code",[s("span",{pre:!0,attrs:{class:"token command"}},[t._v("$ git log"),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v(" --oneline")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v(" --decorate")])]),t._v("\nccc3333 (HEAD -> master) A third commit\nbbb2222 A second commit\naaa1111 A first commit\n9999999 Initial commit\n\n")])])]),s("p",[t._v("Once you've made your changes, you can add them to the index as usual, then commit them using the "),s("code",[t._v("--fixup")]),t._v(" argument with a reference to the commit you want to squash into:")]),t._v(" "),s("div",{staticClass:"language-git extra-class"},[s("pre",{pre:!0,attrs:{class:"language-git"}},[s("code",[s("span",{pre:!0,attrs:{class:"token command"}},[t._v("$ git add .")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token command"}},[t._v("$ git commit"),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v(" --fixup")]),t._v(" bbb2222")]),t._v("\n[my-feature-branch ddd4444] fixup! A second commit\n\n")])])]),s("p",[t._v("This will create a new commit with a commit message that Git can recognize during an interactive rebase:")]),t._v(" "),s("div",{staticClass:"language-git extra-class"},[s("pre",{pre:!0,attrs:{class:"language-git"}},[s("code",[s("span",{pre:!0,attrs:{class:"token command"}},[t._v("$ git log"),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v(" --oneline")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v(" --decorate")])]),t._v("\nddd4444 (HEAD -> master) fixup! A second commit\nccc3333 A third commit\nbbb2222 A second commit\naaa1111 A first commit\n9999999 Initial commit\n\n")])])]),s("p",[t._v("Next, do an interactive rebase with the "),s("code",[t._v("--autosquash")]),t._v(" argument:")]),t._v(" "),s("div",{staticClass:"language-git extra-class"},[s("pre",{pre:!0,attrs:{class:"language-git"}},[s("code",[s("span",{pre:!0,attrs:{class:"token command"}},[t._v("$ git rebase"),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v(" --autosquash")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v(" --interactive")]),t._v(" HEAD~4")]),t._v("\n\n")])])]),s("p",[t._v("Git will propose you to squash the commit you made with the "),s("code",[t._v("commit --fixup")]),t._v(" into the correct position:")]),t._v(" "),s("div",{staticClass:"language-git extra-class"},[s("pre",{pre:!0,attrs:{class:"language-git"}},[s("code",[t._v("pick aaa1111 A first commit\npick bbb2222 A second commit\nfixup ddd4444 fixup! A second commit\npick ccc3333 A third commit\n\n")])])]),s("p",[t._v("To avoid having to type "),s("code",[t._v("--autosquash")]),t._v(" on every rebase, you can enable this option by default:")]),t._v(" "),s("div",{staticClass:"language-git extra-class"},[s("pre",{pre:!0,attrs:{class:"language-git"}},[s("code",[s("span",{pre:!0,attrs:{class:"token command"}},[t._v("$ git config"),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v(" --global")]),t._v(" rebase.autosquash true")]),t._v("\n\n")])])]),s("h2",{attrs:{id:"autosquashing-and-fixups"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#autosquashing-and-fixups"}},[t._v("#")]),t._v(" Autosquashing and fixups")]),t._v(" "),s("p",[t._v("When committing changes it is possible to specify that the commit will in future be squashed to another commit and this can be done like so,")]),t._v(" "),s("p",[s("code",[t._v("git commit --squash=[commit hash of commit to which this commit will be squashed to]")])]),t._v(" "),s("p",[t._v("One might also use, "),s("code",[t._v("--fixup=[commit hash]")]),t._v(" alternatively to fixup.")]),t._v(" "),s("p",[t._v("It is also possible to use words from the commit message instead of the commit hash, like so,")]),t._v(" "),s("p",[s("code",[t._v("git commit --squash :/things")])]),t._v(" "),s("p",[t._v("where the most recent commit with the word 'things' would be used.")]),t._v(" "),s("p",[t._v("These commits' message would begin with "),s("code",[t._v("'fixup!'")]),t._v(" or "),s("code",[t._v("'squash!'")]),t._v(" followed by the rest of the commit message to which these commits will be squashed to.")]),t._v(" "),s("p",[t._v("When rebasing "),s("code",[t._v("--autosquash")]),t._v(" flag should be used to use the autosquash/fixup feature.")]),t._v(" "),s("h4",{attrs:{id:"remarks"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#remarks"}},[t._v("#")]),t._v(" Remarks")]),t._v(" "),s("h3",{attrs:{id:"what-is-squashing"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#what-is-squashing"}},[t._v("#")]),t._v(" What is squashing?")]),t._v(" "),s("p",[t._v("Squashing is the process of taking multiple commits and combining them into a single commit encapsulating all the changes from the initial commits.")]),t._v(" "),s("h3",{attrs:{id:"squashing-and-remote-branches"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#squashing-and-remote-branches"}},[t._v("#")]),t._v(" Squashing and Remote Branches")]),t._v(" "),s("p",[t._v("Pay special attention when squashing commits on a branch that is tracking a remote branch; if you squash a commit that has already been pushed to a remote branch, the two branches will be diverged, and you will have to use "),s("code",[t._v("git push -f")]),t._v(" to force those changes onto the remote branch. "),s("strong",[t._v("Be aware that this can cause issues for others tracking that remote branch")]),t._v(", so caution should be used when force-pushing squashed commits onto public or shared repositories.")]),t._v(" "),s("p",[t._v('If the project is hosted on GitHub, you can enable "force push protection" on some branches, like '),s("code",[t._v("master")]),t._v(", by adding it to "),s("code",[t._v("Settings")]),t._v(" - "),s("code",[t._v("Branches")]),t._v(" - "),s("code",[t._v("Protected Branches")]),t._v(".")])])}),[],!1,null,null,null);e.default=o.exports}}]);