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!
This commit is contained in:
Jakob Degen 2020-09-25 15:30:29 -04:00 committed by Joshua Nelson
parent fb23f10071
commit 7f590fa025
2 changed files with 51 additions and 46 deletions

View File

@ -31,7 +31,7 @@
- [Introduction](./contributing.md) - [Introduction](./contributing.md)
- [About the compiler team](./compiler-team.md) - [About the compiler team](./compiler-team.md)
- [Using git](./git.md) - [Using Git](./git.md)
- [Mastering @rustbot](./rustbot.md) - [Mastering @rustbot](./rustbot.md)
- [Walkthrough: a typical contribution](./walkthrough.md) - [Walkthrough: a typical contribution](./walkthrough.md)
- [Bug Fix Procedure](./bug-fix-procedure.md) - [Bug Fix Procedure](./bug-fix-procedure.md)

View File

@ -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 contribute, you'll need some familiarity with its features so that your changes
can be incorporated into the compiler. 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 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 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 started sections of [this tutorial from Atlassian][atlassian-git]. GitHub also
provides [documentation] and [guides] for beginners, or you can consult the 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 [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 [documentation]: https://docs.github.com/en/github/getting-started-with-github/set-up-git
[guides]: https://guides.github.com/introduction/git-handbook/ [guides]: https://guides.github.com/introduction/git-handbook/
## Prequisites ## 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 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. generally do the same things.
[rust-lang/rust]: https://github.com/rust-lang/rust [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 rust-lang/rust repo via
```sh ```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 if you're using HTTPS, or
```sh ```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. if you're using SSH.
@ -51,7 +51,7 @@ and PRs:
1. Ensure that you're making your changes on top of master: 1. Ensure that you're making your changes on top of master:
`git checkout 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`. 3. Make a new branch for your change: `git checkout -b issue-12345-fix`.
4. Make some changes to the repo and test them. 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` 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 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 updates. You can use `git status` to check if there are any files you forgot
to stage. 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. 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 [ghpullrequest]: https://guides.github.com/activities/forking/#making-a-pull-request
@ -82,7 +82,7 @@ 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 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 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. update it with the most recent changes.
### Rebasing ### Rebasing
@ -91,10 +91,10 @@ You're now ready to start the rebasing process. Check out the branch with your
changes and execute `git rebase master`. changes and execute `git rebase master`.
When you rebase a branch on master, all the changes on your branch are 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 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 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 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 that have been made. You can tell that this happened because you'll see
lines in the output that look like lines in the output that look like
@ -113,24 +113,24 @@ Your code
>>>>>>> 8fbf656... Commit fixes 12345 >>>>>>> 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 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 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, decide how to deal with the conflict. You may want to keep your changes,
keep the changes on master, or combine the two. 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 particular conflict. Edit the file to make the changes you want and remove the
`<<<<<<<`, `=======` and `>>>>>>>` lines in the process. Second, check the `<<<<<<<`, `=======` and `>>>>>>>` lines in the process. Second, check the
surrounding code. If there was a conflict, its because someone else changed the surrounding code. If there was a conflict, its likely there are some logical
same code you did. That means its likely there are some logical errors lying errors lying around too! It's a good idea to run `x.py check` here to make sure
around too! there are no glaring errors.
Once you're all done fixing the conflicts, you need to stage the files that had 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 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 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: 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. 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 The advice this gives is incorrect! Because of Rust's
`git pull` will create a merge commit, defeating the point of your rebase. Use ["no-merge" policy](#no-merge-policy) the merge commit created by `git pull`
`git push -f` instead. 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 ## 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 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 the rebase conflicts are extremely severe, you can use
reapply the changes you made on top of the updated code will be too much of a `git rebase --interactive master` to gain more control over the process. This
headache. In this case, you can use the interactive rebase feature via allows you to choose to skip commits, edit the commits that you do not skip,
`git rebase -i master` to gain more control over the process. This allows you change the order in which they are applied, or "squash" them into each other.
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 Alternatively, you can sacrifice the commit history like this:
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 # squash all the changes into one commit so you only have to worry about conflicts once
meaningful commit message. Run `git rebase -i HEAD~2` to edit the last two git rebase -i $(git merge-base master) # and squash all changes along the way
commits so you can merge them together. By selecting the `-i` option, you give git rebase master
yourself the opportunity to edit the rebase, similarly to above. This way you # fix all merge conflicts
can request to have the most recent commit squashed into its parent. 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 ## No-Merge Policy