From 78857338ab713a2b9492e40315ea4daf5e84ef92 Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Thu, 24 Sep 2020 10:10:52 -0400 Subject: [PATCH 1/3] Add a section on using git. This section addresses the biggest issues that new contributors, especially those with limited familiarity with git, are likely to face. This is still a WIP. Thanks to jyn for the recommended improvements! --- src/SUMMARY.md | 1 + src/git.md | 203 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 src/git.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 5bd038780..eaefb2ed4 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -33,6 +33,7 @@ - [About the compiler team](./compiler-team.md) - [Mastering @rustbot](./rustbot.md) - [Walkthrough: a typical contribution](./walkthrough.md) +- [Using git](./git.md) - [Bug Fix Procedure](./bug-fix-procedure.md) - [Implementing new features](./implementing_new_features.md) - [Stability attributes](./stability.md) diff --git a/src/git.md b/src/git.md new file mode 100644 index 000000000..07e30c2de --- /dev/null +++ b/src/git.md @@ -0,0 +1,203 @@ +# Using git + +The Rust project uses [git] to manage its source code. In order to +contribute, you'll need some familiarity with its features so that your changes +can be incorporated into the compiler. + +[git]: https://git-scm.com + +The goal of this page is to cover some of the more common questions and +problems new contributors face. Although some git basics will be covered here, +if you have never used git or GitHub before you may find that this is still a +little too fast for you. In that case, it would make sense to first read some +introductions to git, such as the Beginner and Getting started sections of +[this tutorial from Atlassian][atlassian-git]. GitHub also provides +[documentation] and [guides] for beginners. + +[atlassian-git]: https://www.atlassian.com/git/tutorials/what-is-version-control +[documentation]: https://docs.github.com/en/github/getting-started-with-github/set-up-git +[guides]: https://guides.github.com/introduction/git-handbook/ + +Although this page should get you to a point where you can start contributing, +learning more git is almost certainly a good use of your time if you want to +keep contributing. There are many tutorials online for those folks that are +newer which combine excellently with man pages and official documentation. + +## Prequisites + +We'll assume that you've installed git, forked [rust-lang/rust], and cloned the +forked repo to your PC. We'll also use the command line interface to interact +with git; there are also a number of GUIs and IDE integrations that can +generally do the same things. + +[rust-lang/rust]: https://github.com/rust-lang/rust + +If you've cloned your fork, then you will be able to reference it with `origin` +in your local repo. It may be helpful to also set up a remote for the official +rust-lang/rust repo via + +```sh +git remote add rust https://github.com/rust-lang/rust.git +``` + +if you're using HTTPS, or + +```sh +git remote add rust git@github.com:rust-lang/rust.git +``` + +if you're using SSH. + +## Standard Process + +Below is the normal procedure that you're likely to use for most minor changes +and PRs: + + 1. Ensure that you're making your changes on top of master: + `git checkout master`. + 2. Get the latest changes from the Rust repo: `git pull rust master`. + 3. Make a new branch for your change: `git checkout -b issue-12345-fix`. + 4. Make some changes to the repo and test them. + 5. Stage your changes via `git add src/changed/file.rs src/another/change.rs` + and then commit them with `git commit`. Of course, making intermediate commits + may be a good idea as well. Avoid `git add .`, as it makes it too easy to + unintentionally commit changes that should not be committed, such as submodule + updates. You can use `git status` to check if there are any files you forgot + to stage. + 6. Push your changes to your fork: `git push -u origin issue-12345-fix`. + 7. [Open a PR][ghpullrequest] from your fork to rust-lang/rust's master branch. + +[ghpullrequest]: https://guides.github.com/activities/forking/#making-a-pull-request + +If your reviewer requests changes, the procedure for those changes looks much +the same, with some steps skipped: + + 1. Ensure that you're making changes to the most recent version of your code: + `git checkout issue-12345-fix`. + 2. Make, stage, and commit your additional changes just like before. + 3. Push those changes to your fork: `git push`. + +## Conflicts + +When you edit your code locally, you are making changes to the version of +rust-lang/rust that existed the last time you ran `git pull rust master` on +your master branch. As such, when you submit your PR it is possible that some +of the changes that have been made to rust-lang/rust since then are in conflict +with the changes you've made; maybe someone else changed the same lines of +code, or git cannot figure out how to merge your changes with the others for +another reason. + +When this happens, you need to resolve the conflicts before your changes can be +merged. First, get a local copy of the conflicting changes. Checkout your local +master branch with `git checkout master`. Then, `git pull rust master` to +update it with the most recent changes. + +### Rebasing + +You're now ready to start the rebasing process. Check out the branch with your +changes, and then execute `git rebase master`. + +First, a little background: In git, commits are stored as "diffs" which are a +record of all the changes that a commit made to its parent. When you rebase a +branch, all the changes in the commits on that branch are reapplied on the +branch you are rebasing on top of (in this case master). In other words, git +tries to pretend that the changes you made to the old version of master were +instead made to the new version of master. + +During rebasing, you should expect to encounter at least one "rebase conflict." +This happens when git's attempt to reapply the changes onto the more recent +version of master fails because your changes conflicted with other changes that +have been made since then. You can tell that this happened because you'll see +lines in the output that look like + +``` +CONFLICT (content): Merge conflict in file.rs +``` + +When you open these files, you'll see sections of the form + +``` +<<<<<<< HEAD +Original code +======= +Your code +>>>>>>> 8fbf656... Commit fixes 12345 +``` + +This represents the lines in the file that git could not figure out how to +rebase. The section between `<<<<<<< HEAD` and `=======` has the code from +master, while the other side has your version of the code. You'll need to +decide how to deal with the conflict. You may want to keep your changes, +keep the changes on master, or combine the two. + +Generally, resovling the conflict consists of two steps: First, fix the +particular conflict. Edit the file to make the changes you want and remove the +`<<<<<<<`, `=======` and `>>>>>>>` lines in the process. Second, check the +surrounding code. If there was a conflict, its because someone else changed the +same code you did. That means its likely there are some logical errors lying +around too! + +Once you're all done fixing the conflicts, you need to stage the files that had +conflicts in them via `git add`. Afterwards, run `git rebase --continue` to let +git know that you've resolved the conflicts and it should finish the rebase. +Finally, once the rebase has succeeded, you'll want to update the associated +branch on your fork with `git push -f`. + +Note that `git push` will not work properly and say something like this: + +``` + ! [rejected] issue-xxxxx -> issue-xxxxx (non-fast-forward) +error: failed to push some refs to 'https://github.com/username/rust.git' +hint: Updates were rejected because the tip of your current branch is behind +hint: its remote counterpart. Integrate the remote changes (e.g. +hint: 'git pull ...') before pushing again. +hint: See the 'Note about fast-forwards' in 'git push --help' for details. +``` + +The advice this gives is incorrect! Because of the "no-merge" policy, running +`git pull` will create a merge commit, defeating the point of your rebase. Use +`git push -f` instead. + +## Advanced Rebasing + +Sometimes, you may want to perform a more complicated rebase. There are two +common scenarios that might call for this. + +If your branch contains multiple consecutive rewrites of the same code, or if +the rebase conflicts are extremely severe, it is possible that just trying to +reapply the changes you made on top of the updated code will be too much of a +headache. In this case, you can use the interactive rebase feature via +`git rebase -i master` to gain more control over the process. This allows you +to choose to skip commits because they represent changes you no longer need, +edit the commits that you do not skip, or change the order in which they are +applied. + +The other common scenario is if you are asked to or want to "squash" multiple +commits into each other. The most common example of this is likely if you +forgot to run `x.py tidy` before committing. Your PR will need to be revised, +but a single commit at the end with message "fixup tidy issue" is usually +unhelpful, and it is easier for everyone else if you combine that commit with +another that has a more meaningful commit message. In this case, you'll want to +run `git rebase -i HEAD~2` to edit the last two commits and merge them +together. Essentially, this reapplies the last two commits on top of your +current branch; this is of course a no-op, since that is where they are +already. However, by selecting the `-i` option, you give yourself the +opportunity to edit the rebase first, just like before. This way you can +request to have the most recent commit squashed into its parent. + +## No-Merge Policy + +The rust-lang/rust repo uses what is known as a "rebase workflow." This means +that merge commits in PRs are not accepted. As a result, if you are running +`git merge` locally, chances are good that you should be rebasing instead. Of +course, this is not always true; if your merge will just be a fast-forward, +like the merges that `git pull` usually performs, then no merge commit is +created and you have nothing to worry about. Running `git config merge.ff only` +once will prevent the creation of merge commits will help ensure you don't make +a mistake here. + +There are a number of reasons for this decision and like all others, it is a +tradeoff. The main advantage is the (mostly) linear commit history. This +greatly simplifies bisecting. TODO: There are other advantages to a rebase +workflow, but I would like to focus on the ones that people in the Rust project +consider most relevant, so I'm going to leave this unfinished for now. From 360d4a542e02e4183b9617c76313f56d80f32a6b Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Thu, 24 Sep 2020 16:48:55 -0400 Subject: [PATCH 2/3] Edit using git page for brevity and clarity. The previous iteration of the page was often wordy and occasionally unclear. This has been cleaned up in places. Additionally, the TODO in the no-merge policy section has been removed and addressed. --- src/SUMMARY.md | 2 +- src/git.md | 86 ++++++++++++++++++++------------------------------ 2 files changed, 36 insertions(+), 52 deletions(-) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index eaefb2ed4..0e52a2e08 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -31,9 +31,9 @@ - [Introduction](./contributing.md) - [About the compiler team](./compiler-team.md) +- [Using git](./git.md) - [Mastering @rustbot](./rustbot.md) - [Walkthrough: a typical contribution](./walkthrough.md) -- [Using git](./git.md) - [Bug Fix Procedure](./bug-fix-procedure.md) - [Implementing new features](./implementing_new_features.md) - [Stability attributes](./stability.md) diff --git a/src/git.md b/src/git.md index 07e30c2de..b6b852587 100644 --- a/src/git.md +++ b/src/git.md @@ -8,25 +8,21 @@ can be incorporated into the compiler. The goal of this page is to cover some of the more common questions and problems new contributors face. Although some git basics will be covered here, -if you have never used git or GitHub before you may find that this is still a -little too fast for you. In that case, it would make sense to first read some -introductions to git, such as the Beginner and Getting started sections of -[this tutorial from Atlassian][atlassian-git]. GitHub also provides -[documentation] and [guides] for beginners. +if you find that this is still a little too fast for you, it might make sense +to first read some introductions to git, such as the Beginner and Getting +started sections of [this tutorial from Atlassian][atlassian-git]. GitHub also +provides [documentation] and [guides] for beginners, or you can consult the +more in depth [book from git]. +[book from git]: https://git-scm.com/book/en/v2/ [atlassian-git]: https://www.atlassian.com/git/tutorials/what-is-version-control [documentation]: https://docs.github.com/en/github/getting-started-with-github/set-up-git [guides]: https://guides.github.com/introduction/git-handbook/ -Although this page should get you to a point where you can start contributing, -learning more git is almost certainly a good use of your time if you want to -keep contributing. There are many tutorials online for those folks that are -newer which combine excellently with man pages and official documentation. - ## Prequisites We'll assume that you've installed git, forked [rust-lang/rust], and cloned the -forked repo to your PC. We'll also use the command line interface to interact +forked repo to your PC. We'll use the command line interface to interact with git; there are also a number of GUIs and IDE integrations that can generally do the same things. @@ -80,34 +76,27 @@ the same, with some steps skipped: ## Conflicts When you edit your code locally, you are making changes to the version of -rust-lang/rust that existed the last time you ran `git pull rust master` on -your master branch. As such, when you submit your PR it is possible that some -of the changes that have been made to rust-lang/rust since then are in conflict -with the changes you've made; maybe someone else changed the same lines of -code, or git cannot figure out how to merge your changes with the others for -another reason. +rust-lang/rust that existed when you created your feature branch. As such, when +you submit your PR it is possible that some of the changes that have been made +to rust-lang/rust since then are in conflict with the changes you've made. When this happens, you need to resolve the conflicts before your changes can be -merged. First, get a local copy of the conflicting changes. Checkout your local -master branch with `git checkout master`. Then, `git pull rust master` to +merged. First, get a local copy of the conflicting changes: Checkout your local +master branch with `git checkout master`, then `git pull rust master` to update it with the most recent changes. ### Rebasing You're now ready to start the rebasing process. Check out the branch with your -changes, and then execute `git rebase master`. - -First, a little background: In git, commits are stored as "diffs" which are a -record of all the changes that a commit made to its parent. When you rebase a -branch, all the changes in the commits on that branch are reapplied on the -branch you are rebasing on top of (in this case master). In other words, git -tries to pretend that the changes you made to the old version of master were -instead made to the new version of master. - -During rebasing, you should expect to encounter at least one "rebase conflict." -This happens when git's attempt to reapply the changes onto the more recent -version of master fails because your changes conflicted with other changes that -have been made since then. You can tell that this happened because you'll see +changes and execute `git rebase master`. + +When you rebase a branch on master, all the changes on your branch are +reapplied to the most recent version of master. In other words, git tries to +pretend that the changes you made to the old version of master were instead +made to the new version of master. During this process, you should expect to +encounter at least one "rebase conflict." This happens when git's attempt to +reapply the changes fails because your changes conflicted with other changes +that have been made. You can tell that this happened because you'll see lines in the output that look like ``` @@ -140,8 +129,8 @@ around too! Once you're all done fixing the conflicts, you need to stage the files that had conflicts in them via `git add`. Afterwards, run `git rebase --continue` to let git know that you've resolved the conflicts and it should finish the rebase. -Finally, once the rebase has succeeded, you'll want to update the associated -branch on your fork with `git push -f`. +Once the rebase has succeeded, you'll want to update the associated branch on +your fork with `git push -f`. Note that `git push` will not work properly and say something like this: @@ -173,17 +162,13 @@ edit the commits that you do not skip, or change the order in which they are applied. The other common scenario is if you are asked to or want to "squash" multiple -commits into each other. The most common example of this is likely if you -forgot to run `x.py tidy` before committing. Your PR will need to be revised, -but a single commit at the end with message "fixup tidy issue" is usually -unhelpful, and it is easier for everyone else if you combine that commit with -another that has a more meaningful commit message. In this case, you'll want to -run `git rebase -i HEAD~2` to edit the last two commits and merge them -together. Essentially, this reapplies the last two commits on top of your -current branch; this is of course a no-op, since that is where they are -already. However, by selecting the `-i` option, you give yourself the -opportunity to edit the rebase first, just like before. This way you can -request to have the most recent commit squashed into its parent. +commits into each other. If you PR needs only a minor revision, a single commit +at the end with message "fixup small issue" is usually unhelpful, and it is +easier for everyone if you combine that commit with another that has a more +meaningful commit message. Run `git rebase -i HEAD~2` to edit the last two +commits so you can merge them together. By selecting the `-i` option, you give +yourself the opportunity to edit the rebase, similarly to above. This way you +can request to have the most recent commit squashed into its parent. ## No-Merge Policy @@ -193,11 +178,10 @@ that merge commits in PRs are not accepted. As a result, if you are running course, this is not always true; if your merge will just be a fast-forward, like the merges that `git pull` usually performs, then no merge commit is created and you have nothing to worry about. Running `git config merge.ff only` -once will prevent the creation of merge commits will help ensure you don't make -a mistake here. +once will ensure that all the merges you perform are of this type, so that you +cannot make a mistake. There are a number of reasons for this decision and like all others, it is a -tradeoff. The main advantage is the (mostly) linear commit history. This -greatly simplifies bisecting. TODO: There are other advantages to a rebase -workflow, but I would like to focus on the ones that people in the Rust project -consider most relevant, so I'm going to leave this unfinished for now. +tradeoff. The main advantage is the generally linear commit history. This +greatly simplifies bisecting and makes the history and commit log much easier +to follow and understand. From 074371e5fc0fea401450b0ead50605f1db7c9103 Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Fri, 25 Sep 2020 15:30:29 -0400 Subject: [PATCH 3/3] Incorporated suggestions into git page and edit for more brevity. The Advanced Rebasing section has been mostly rewritten to include both a major suggestion from jyn and a general rewrite. Additional thanks to camelid for some suggestions! --- src/SUMMARY.md | 2 +- src/git.md | 97 ++++++++++++++++++++++++++------------------------ 2 files changed, 52 insertions(+), 47 deletions(-) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 0e52a2e08..f3ebe4da8 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -31,7 +31,7 @@ - [Introduction](./contributing.md) - [About the compiler team](./compiler-team.md) -- [Using git](./git.md) +- [Using Git](./git.md) - [Mastering @rustbot](./rustbot.md) - [Walkthrough: a typical contribution](./walkthrough.md) - [Bug Fix Procedure](./bug-fix-procedure.md) diff --git a/src/git.md b/src/git.md index b6b852587..9f025ff61 100644 --- a/src/git.md +++ b/src/git.md @@ -1,29 +1,29 @@ -# Using git +# Using Git -The Rust project uses [git] to manage its source code. In order to +The Rust project uses [Git] to manage its source code. In order to contribute, you'll need some familiarity with its features so that your changes can be incorporated into the compiler. -[git]: https://git-scm.com +[Git]: https://git-scm.com The goal of this page is to cover some of the more common questions and -problems new contributors face. Although some git basics will be covered here, +problems new contributors face. Although some Git basics will be covered here, if you find that this is still a little too fast for you, it might make sense -to first read some introductions to git, such as the Beginner and Getting +to first read some introductions to Git, such as the Beginner and Getting started sections of [this tutorial from Atlassian][atlassian-git]. GitHub also provides [documentation] and [guides] for beginners, or you can consult the -more in depth [book from git]. +more in depth [book from Git]. -[book from git]: https://git-scm.com/book/en/v2/ +[book from Git]: https://git-scm.com/book/en/v2/ [atlassian-git]: https://www.atlassian.com/git/tutorials/what-is-version-control [documentation]: https://docs.github.com/en/github/getting-started-with-github/set-up-git [guides]: https://guides.github.com/introduction/git-handbook/ ## Prequisites -We'll assume that you've installed git, forked [rust-lang/rust], and cloned the +We'll assume that you've installed Git, forked [rust-lang/rust], and cloned the forked repo to your PC. We'll use the command line interface to interact -with git; there are also a number of GUIs and IDE integrations that can +with Git; there are also a number of GUIs and IDE integrations that can generally do the same things. [rust-lang/rust]: https://github.com/rust-lang/rust @@ -33,13 +33,13 @@ in your local repo. It may be helpful to also set up a remote for the official rust-lang/rust repo via ```sh -git remote add rust https://github.com/rust-lang/rust.git +git remote add upstream https://github.com/rust-lang/rust.git ``` if you're using HTTPS, or ```sh -git remote add rust git@github.com:rust-lang/rust.git +git remote add upstream git@github.com:rust-lang/rust.git ``` if you're using SSH. @@ -51,7 +51,7 @@ and PRs: 1. Ensure that you're making your changes on top of master: `git checkout master`. - 2. Get the latest changes from the Rust repo: `git pull rust master`. + 2. Get the latest changes from the Rust repo: `git pull upstream master`. 3. Make a new branch for your change: `git checkout -b issue-12345-fix`. 4. Make some changes to the repo and test them. 5. Stage your changes via `git add src/changed/file.rs src/another/change.rs` @@ -60,7 +60,7 @@ and PRs: unintentionally commit changes that should not be committed, such as submodule updates. You can use `git status` to check if there are any files you forgot to stage. - 6. Push your changes to your fork: `git push -u origin issue-12345-fix`. + 6. Push your changes to your fork: `git push --set-upstream origin issue-12345-fix`. 7. [Open a PR][ghpullrequest] from your fork to rust-lang/rust's master branch. [ghpullrequest]: https://guides.github.com/activities/forking/#making-a-pull-request @@ -82,19 +82,19 @@ to rust-lang/rust since then are in conflict with the changes you've made. When this happens, you need to resolve the conflicts before your changes can be merged. First, get a local copy of the conflicting changes: Checkout your local -master branch with `git checkout master`, then `git pull rust master` to +master branch with `git checkout master`, then `git pull upstream master` to update it with the most recent changes. ### Rebasing -You're now ready to start the rebasing process. Check out the branch with your +You're now ready to start the rebasing process. Checkout the branch with your changes and execute `git rebase master`. When you rebase a branch on master, all the changes on your branch are -reapplied to the most recent version of master. In other words, git tries to +reapplied to the most recent version of master. In other words, Git tries to pretend that the changes you made to the old version of master were instead made to the new version of master. During this process, you should expect to -encounter at least one "rebase conflict." This happens when git's attempt to +encounter at least one "rebase conflict." This happens when Git's attempt to reapply the changes fails because your changes conflicted with other changes that have been made. You can tell that this happened because you'll see lines in the output that look like @@ -113,24 +113,24 @@ Your code >>>>>>> 8fbf656... Commit fixes 12345 ``` -This represents the lines in the file that git could not figure out how to +This represents the lines in the file that Git could not figure out how to rebase. The section between `<<<<<<< HEAD` and `=======` has the code from master, while the other side has your version of the code. You'll need to decide how to deal with the conflict. You may want to keep your changes, keep the changes on master, or combine the two. -Generally, resovling the conflict consists of two steps: First, fix the +Generally, resolving the conflict consists of two steps: First, fix the particular conflict. Edit the file to make the changes you want and remove the `<<<<<<<`, `=======` and `>>>>>>>` lines in the process. Second, check the -surrounding code. If there was a conflict, its because someone else changed the -same code you did. That means its likely there are some logical errors lying -around too! +surrounding code. If there was a conflict, its likely there are some logical +errors lying around too! It's a good idea to run `x.py check` here to make sure +there are no glaring errors. Once you're all done fixing the conflicts, you need to stage the files that had conflicts in them via `git add`. Afterwards, run `git rebase --continue` to let -git know that you've resolved the conflicts and it should finish the rebase. +Git know that you've resolved the conflicts and it should finish the rebase. Once the rebase has succeeded, you'll want to update the associated branch on -your fork with `git push -f`. +your fork with `git push --force-with-lease`. Note that `git push` will not work properly and say something like this: @@ -143,32 +143,37 @@ hint: 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details. ``` -The advice this gives is incorrect! Because of the "no-merge" policy, running -`git pull` will create a merge commit, defeating the point of your rebase. Use -`git push -f` instead. +The advice this gives is incorrect! Because of Rust's +["no-merge" policy](#no-merge-policy) the merge commit created by `git pull` +will not be allowed in the final PR, in addition to defeating the point of the +rebase! Use `git push --force-with-lease` instead. ## Advanced Rebasing -Sometimes, you may want to perform a more complicated rebase. There are two -common scenarios that might call for this. - If your branch contains multiple consecutive rewrites of the same code, or if -the rebase conflicts are extremely severe, it is possible that just trying to -reapply the changes you made on top of the updated code will be too much of a -headache. In this case, you can use the interactive rebase feature via -`git rebase -i master` to gain more control over the process. This allows you -to choose to skip commits because they represent changes you no longer need, -edit the commits that you do not skip, or change the order in which they are -applied. - -The other common scenario is if you are asked to or want to "squash" multiple -commits into each other. If you PR needs only a minor revision, a single commit -at the end with message "fixup small issue" is usually unhelpful, and it is -easier for everyone if you combine that commit with another that has a more -meaningful commit message. Run `git rebase -i HEAD~2` to edit the last two -commits so you can merge them together. By selecting the `-i` option, you give -yourself the opportunity to edit the rebase, similarly to above. This way you -can request to have the most recent commit squashed into its parent. +the rebase conflicts are extremely severe, you can use +`git rebase --interactive master` to gain more control over the process. This +allows you to choose to skip commits, edit the commits that you do not skip, +change the order in which they are applied, or "squash" them into each other. + +Alternatively, you can sacrifice the commit history like this: + +``` +# squash all the changes into one commit so you only have to worry about conflicts once +git rebase -i $(git merge-base master) # and squash all changes along the way +git rebase master +# fix all merge conflicts +git rebase --continue +``` + +"Squashing" commits into each other causes them to be merged into a single +commit. Both the upside and downside of this is that it simplifies the history. +On the one hand, you lose track of the steps in which changes were made, but +the history becomes easier to work with. + +You also may want to squash just the last few commits together, possibly +because they only represent "fixups" and not real changes. For example, +`git rebase --interactive HEAD~2` will allow you to edit the two commits only. ## No-Merge Policy