|
|
# Merge Process
|
|
|
|
|
|
Network team merge process, setup instructions, and notes.
|
|
|
|
|
|
This page explains how to merge patches into Tor. For the rules about **when** to merge patches into Tor, see the [[org/teams/NetworkTeam/MergePolicy|MergePolicy]] document.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## How do you do a Merge?
|
|
|
|
|
|
### Configuring your Environment
|
|
|
|
|
|
[draft]
|
|
|
|
|
|
#### Master and Backport Merges
|
|
|
|
|
|
##### 1. Make sure you have the git hooks installed
|
|
|
|
|
|
You can find the hooks in `tor/scripts/git/`. They need to be copied into tor/.git/hooks, without the extension:
|
|
|
* tor/scripts/git/post-merge.git-hook -> .git/hooks/post-merge
|
|
|
* (repeat for the other hooks)
|
|
|
|
|
|
Q: How do I keep the git hooks up to date?
|
|
|
A: Install the post-merge (post pull) hook, so git logs a message when the hooks are updated in master. (See #29588.)
|
|
|
|
|
|
##### 2. Clone and configure your git repository
|
|
|
|
|
|
You might find it easier to use a separate git repository for merges and regular coding.
|
|
|
|
|
|
**Automatic Setup**
|
|
|
|
|
|
Set TOR_FULL_GIT_PATH in your .profile, and run `git-setup-dirs.sh`.
|
|
|
(This script sets up backport worktrees as well - you can just ignore them.)
|
|
|
|
|
|
**Manual Setup**
|
|
|
|
|
|
Configure your repository with:
|
|
|
|
|
|
* git-rw.torproject.org:tor.git as "origin" and
|
|
|
* github.com/torproject/tor.git as "tor-github".
|
|
|
|
|
|
```
|
|
|
$ git remote add tor-github https://github.com/torproject/tor.git
|
|
|
```
|
|
|
|
|
|
Piece of advice here. Because git default behavior of "git push" is to use
|
|
|
"origin", then mistake can happen where one of us can push a personal branch
|
|
|
to our upstream tor.git.
|
|
|
|
|
|
For that I nullify the "pushurl" of origin with:
|
|
|
|
|
|
```
|
|
|
[remote "origin"]
|
|
|
fetch = +refs/heads/*:refs/remotes/origin/*
|
|
|
url = https://git.torproject.org/tor.git
|
|
|
pushurl = "Don't push personal branches to origin!"
|
|
|
```
|
|
|
|
|
|
To push now, I created an "upstream" remote so when I push commits upstream, I
|
|
|
have to explicitly type in:
|
|
|
|
|
|
```
|
|
|
$ git push upstream <branch>
|
|
|
```
|
|
|
|
|
|
(The git-push-all.sh allows you to specific the name of the "upstream"
|
|
|
branch).
|
|
|
|
|
|
To add the upstream remote properly:
|
|
|
|
|
|
```
|
|
|
$ git remote add upstream https://git.torproject.org/tor.git
|
|
|
$ git remote set-url --push upstream ssh://git@git-rw.torproject.org/tor.git
|
|
|
```
|
|
|
|
|
|
Make sure you have PRs from tor-github set up to be named
|
|
|
tor-github/pr/NNN, where NNN is the number of the PR.
|
|
|
|
|
|
In your gitconfig:
|
|
|
|
|
|
```
|
|
|
[remote "tor-github"]
|
|
|
fetch = +refs/heads/*:refs/remotes/tor-github/*
|
|
|
fetch = +refs/pull/*:refs/remotes/tor-github/pr/*
|
|
|
```
|
|
|
|
|
|
This sets up pull requests as:
|
|
|
* tor-github/pr/NNNN/head - the branch you want to merge
|
|
|
* tor-github/pr/NNNN/merge - the branch github made as a test merge for CI. Only exists if the merge is clean.
|
|
|
Some git repositories default to head when you use tor-github/pr/NNNN.
|
|
|
|
|
|
##### 3. Make sure you have merge permissions
|
|
|
|
|
|
Set up SSH keys using Tor's LDAP:
|
|
|
* https://db.torproject.org/doc-mail.html
|
|
|
|
|
|
Check your access:
|
|
|
```
|
|
|
$ ssh git@git-rw.torproject.org | grep W
|
|
|
```
|
|
|
|
|
|
For more details, see [org/operations/services/git.torproject.org](org/operations/services/git.torproject.org).
|
|
|
|
|
|
#### Backport Merges Only
|
|
|
|
|
|
##### 4. Make sure you have the git scripts installed
|
|
|
|
|
|
You can find the scripts in `tor/scripts/git/`. They need to be copied into your $PATH:
|
|
|
* tor/scripts/git/git-pull-all.sh -> ~/bin/git-pull-all.sh
|
|
|
* (repeat for the other scripts)
|
|
|
|
|
|
You will need to customise these scripts to your own environment, using the environmental variables listed in the script's --help.
|
|
|
|
|
|
These scripts require a recent bash that supports arrays.
|
|
|
|
|
|
##### 5. Make sure you are using worktrees
|
|
|
|
|
|
You might find it easier to use a separate git repository for merges and regular coding.
|
|
|
|
|
|
**Automatic Setup**
|
|
|
|
|
|
Set TOR_FULL_GIT_PATH in your .profile, and run `git-setup-dirs.sh`.
|
|
|
|
|
|
**Manual Setup**
|
|
|
|
|
|
To use the git-* scripts, you need worktrees. Here is an
|
|
|
example on how to do it properly for let say the "maint-0.3.5" branch and your
|
|
|
worktrees are in "tor-wkt" (relative to tor.git/ you have):
|
|
|
|
|
|
```
|
|
|
$ git worktree add ../tor-wkt/maint-0.3.5 origin/maint-0.3.5
|
|
|
$ cd ../tor-wkt/maint-0.3.5
|
|
|
$ git checkout -b maint-0.3.5
|
|
|
$ git branch --set-upstream-to=origin/maint-0.3.5 maint-0.3.5
|
|
|
```
|
|
|
|
|
|
So then now within the worktree, you can simply do "git pull" and it will
|
|
|
always fetch the latest from origin/maint-0.3.5 which is important because the
|
|
|
git-pull-all.sh script requires that. These worktrees need to follow upstream
|
|
|
at all times.
|
|
|
|
|
|
Basically, a maintainer should do the above for all maintained branches
|
|
|
(including releases-*).
|
|
|
|
|
|
#### New Maint and Release Branches
|
|
|
|
|
|
Make sure that your git scripts are up to date with the new branches!
|
|
|
|
|
|
**Automatic Setup**
|
|
|
|
|
|
Set TOR_FULL_GIT_PATH in your .profile, and run `git-setup-dirs.sh -u`.
|
|
|
|
|
|
**Manual Setup**
|
|
|
|
|
|
Set up the new maint-* and release-* worktrees, using the instructions in step 5 above.
|
|
|
|
|
|
### Merging a Branch
|
|
|
|
|
|
#### Master Merges
|
|
|
|
|
|
##### 0. Make sure your environment is set up
|
|
|
|
|
|
* git hooks
|
|
|
* tor-github custom remote
|
|
|
|
|
|
##### 1. Make sure you have the latest version of master checked out in your git directory
|
|
|
|
|
|
```
|
|
|
$ git fetch upstream
|
|
|
```
|
|
|
|
|
|
##### 2. Make sure that you have the latest version of the branch you're merging
|
|
|
|
|
|
```
|
|
|
$ git fetch tor-github
|
|
|
```
|
|
|
|
|
|
##### 3. Check all the things you're supposed to check
|
|
|
|
|
|
##### 4. Merge the branch
|
|
|
|
|
|
```
|
|
|
# Sometimes, tor-github/pr/NNNNN will also work
|
|
|
$ git merge tor-github/pr/NNNNN/head
|
|
|
```
|
|
|
|
|
|
##### 5. Push to master
|
|
|
|
|
|
```
|
|
|
$ git push upstream master
|
|
|
```
|
|
|
|
|
|
##### 6. Update the ticket, and wait for CI
|
|
|
|
|
|
See "Backport Merges" Steps 8 & 9 for details.
|
|
|
|
|
|
#### Backport Merges
|
|
|
|
|
|
##### 0. Make sure your environment is set up
|
|
|
|
|
|
* git hooks
|
|
|
* tor-github custom remote
|
|
|
* git scripts
|
|
|
* worktrees
|
|
|
|
|
|
##### 1. Make sure you have the latest version of all supported branches checked out in your worktrees
|
|
|
|
|
|
```
|
|
|
$ git-pull-all.sh
|
|
|
```
|
|
|
|
|
|
##### 2. Make sure that you have the latest version of the branch you're merging
|
|
|
|
|
|
You can get the supported branches and github PRs using:
|
|
|
```
|
|
|
$ git-pull-all.sh
|
|
|
```
|
|
|
|
|
|
##### 3. Check all the things you're supposed to check
|
|
|
|
|
|
##### 4. Go into the earliest target directory where you are merging today, and merge the branch
|
|
|
|
|
|
```
|
|
|
$ cd maint-0.3.5
|
|
|
# Sometimes, tor-github/pr/NNNNN will also work
|
|
|
$ git merge tor-github/pr/NNNNN/head
|
|
|
```
|
|
|
|
|
|
##### 5. If the merge isn't clean, ask the patch author or a stable maintainer what to do
|
|
|
|
|
|
##### 6. Run `git-merge-forward.sh` and verify that there are no conflicts
|
|
|
|
|
|
The merge-forward script will stop after any conflicts.
|
|
|
|
|
|
##### 7. If the merge isn't clean, ask the patch author or a stable maintainer what to do
|
|
|
|
|
|
You can go in to the worktree and fix the conflict yourself, if you can work out how. Let the patch author know on the ticket, and ask them to check your merge.
|
|
|
|
|
|
##### 8. Push all the branches
|
|
|
|
|
|
```
|
|
|
$ git-push-all.sh
|
|
|
```
|
|
|
|
|
|
##### 9. Update the ticket
|
|
|
|
|
|
If you are merging a patch into the earliest series to which it
|
|
|
applies, close the ticket after you merge, and say where you merged
|
|
|
it. If you are merging a patch that is a candidate for backport, move
|
|
|
the ticket into the earliest open milestone to which it applies.
|
|
|
|
|
|
##### 9. Wait for the CI to finish on master
|
|
|
|
|
|
If the CI fails due to practracker errors, update the practracker exceptions file, and push to master again.
|
|
|
(practracker fixes don't need review.) Ask the person who wrote the code to fix the exception.
|
|
|
|
|
|
Make a note on the trac ticket for the PR that caused the error.
|
|
|
|
|
|
### Merging Different Branches into Different Releases
|
|
|
|
|
|
Follow the "Backport Merges" steps 3-5 for each branch you need to merge.
|
|
|
|
|
|
#### Finding Branches to Merge
|
|
|
|
|
|
1. Work out all the maint branches you are merging pull requests into today:
|
|
|
* if you're doing a mainline merge, the maint branches might be:
|
|
|
* the alpha maint branch (if there is one), or
|
|
|
* master (if you'll backport to alpha later)
|
|
|
* if you're doing a backport merge, the maint branches might be:
|
|
|
* the oldest LTS release, or
|
|
|
* newer supported/LTS releases (but not the mainline releases)
|
|
|
* if you're doing a security fix merge:
|
|
|
* merge into all maint branches with the vulnerability
|
|
|
|
|
|
2. Work out the pull request for the earliest maint branch:
|
|
|
a. If there is a pull request based on that maint branch, use that pull request
|
|
|
b. Otherwise, check for a pull request for the next earliest version of Tor, and use that pull request
|
|
|
c. Repeat b. with the Nth earlier version of Tor
|
|
|
|
|
|
3. Work out the maint branches for each other pull request:
|
|
|
a. If there is a pull request based on that maint branch, use that pull request
|
|
|
b. Otherwise, don't merge any pull request into that maint branch
|
|
|
* the pull request for an earlier version should merge forward cleanly
|
|
|
|
|
|
To simplify this process, we usually:
|
|
|
* Merge the change to master
|
|
|
* Wait for testing in an alpha release
|
|
|
* Merge the change to all other versions
|
|
|
|
|
|
#### Doing the Merges
|
|
|
|
|
|
Here's how you do the merges:
|
|
|
1. Find the earliest maint branch you want to merge into today, and the pull request for that maint branch
|
|
|
2. Change to the directory for the maint branch
|
|
|
3. Merge the pull request in to the maint branch
|
|
|
4. Repeat from 2 for the next pull request and its maint branch
|
|
|
5. Once all the pull requests are merged, merge all branches forward
|
|
|
|
|
|
#### Dealing with Merge Conflicts
|
|
|
|
|
|
If there are any merge conflicts, stop! Don't push anything!
|
|
|
Reset your merge directories to the current branches on torproject.org.
|
|
|
Ask for help on the ticket. Include details of the merge conflict.
|
|
|
|
|
|
#### Worked Example
|
|
|
|
|
|
Here is a worked example from https://trac.torproject.org/projects/tor/ticket/29806#comment:18
|
|
|
|
|
|
We want to do a mainline merge into:
|
|
|
* maint-0.4.0
|
|
|
* master
|
|
|
|
|
|
We have these pull requests:
|
|
|
* 0.3.4: https://github.com/torproject/tor/pull/820
|
|
|
* 0.3.5: https://github.com/torproject/tor/pull/821
|
|
|
* master: https://github.com/torproject/tor/pull/822
|
|
|
|
|
|
The earliest branch and pull request are:
|
|
|
* 0.3.5: https://github.com/torproject/tor/pull/821 into maint-0.4.0
|
|
|
* we use the 0.3.5 pull request, because there is no 0.4.0 pull request
|
|
|
|
|
|
The other pull requests are:
|
|
|
* master: https://github.com/torproject/tor/pull/822 into master
|
|
|
|
|
|
Here are the exact steps on the command-line:
|
|
|
```
|
|
|
$ cd ../maint-0.4.0
|
|
|
$ git merge tor-github/pr/821
|
|
|
Auto-merging src/test/test_dir.c
|
|
|
Auto-merging src/feature/dirauth/bwauth.c
|
|
|
Merge made by the 'recursive' strategy.
|
|
|
changes/ticket29806 | 7 ++++++
|
|
|
src/feature/dirauth/bwauth.c | 8 ++++++-
|
|
|
src/test/test_dir.c | 57 ++++++++++++++++++++++++++++++++++++++++++++
|
|
|
3 files changed, 71 insertions(+), 1 deletion(-)
|
|
|
create mode 100644 changes/ticket29806
|
|
|
$ cd ../tor
|
|
|
# If you are using git ~2.20, you will need to merge tor-github/pr/822/head
|
|
|
$ git merge tor-github/pr/822
|
|
|
Merge made by the 'recursive' strategy.
|
|
|
changes/ticket29806 | 7 ++++++
|
|
|
src/feature/dirauth/bwauth.c | 8 +++++-
|
|
|
src/test/test_dir.c | 59 ++++++++++++++++++++++++++++++++++++++++++++
|
|
|
3 files changed, 73 insertions(+), 1 deletion(-)
|
|
|
create mode 100644 changes/ticket29806
|
|
|
$ git-merge-forward.sh
|
|
|
[+] Fetching origin...success
|
|
|
[+] Handling branch
|
|
|
release-0.2.9 Handling branch
|
|
|
[+] Switching branch to release-0.2.9...success
|
|
|
[+] Merging branch origin/release-0.2.9...success
|
|
|
[+] Merging branch maint-0.2.9 into release-0.2.9...success
|
|
|
[+] Handling branch
|
|
|
maint-0.3.4 Handling branch
|
|
|
[+] Switching branch to maint-0.3.4...success
|
|
|
[+] Merging branch origin/maint-0.3.4...success
|
|
|
[+] Merging branch maint-0.2.9 into maint-0.3.4...success
|
|
|
[+] Handling branch
|
|
|
release-0.3.4 Handling branch
|
|
|
[+] Switching branch to release-0.3.4...success
|
|
|
[+] Merging branch origin/release-0.3.4...success
|
|
|
[+] Merging branch maint-0.3.4 into release-0.3.4...success
|
|
|
[+] Handling branch
|
|
|
maint-0.3.5 Handling branch
|
|
|
[+] Switching branch to maint-0.3.5...success
|
|
|
[+] Merging branch origin/maint-0.3.5...success
|
|
|
[+] Merging branch maint-0.3.4 into maint-0.3.5...success
|
|
|
[+] Handling branch
|
|
|
release-0.3.5 Handling branch
|
|
|
[+] Switching branch to release-0.3.5...success
|
|
|
[+] Merging branch origin/release-0.3.5...success
|
|
|
[+] Merging branch maint-0.3.5 into release-0.3.5...success
|
|
|
[+] Handling branch
|
|
|
maint-0.4.0 Handling branch
|
|
|
[+] Switching branch to maint-0.4.0...success
|
|
|
[+] Merging branch origin/maint-0.4.0...success
|
|
|
[+] Merging branch maint-0.3.5 into maint-0.4.0...success
|
|
|
[+] Handling branch
|
|
|
release-0.4.0 Handling branch
|
|
|
[+] Switching branch to release-0.4.0...success
|
|
|
[+] Merging branch origin/release-0.4.0...success
|
|
|
[+] Merging branch maint-0.4.0 into release-0.4.0...success
|
|
|
[+] Handling branch
|
|
|
master Handling branch
|
|
|
[+] Switching branch to master...success
|
|
|
[+] Merging branch origin/master...success
|
|
|
[+] Merging branch maint-0.4.0 into master...success
|
|
|
```
|
|
|
|
|
|
|
|
|
These forward merges were clean merges:
|
|
|
```
|
|
|
[+] Merging branch maint-0.4.0 into release-0.4.0...success
|
|
|
[+] Merging branch maint-0.4.0 into master...success
|
|
|
```
|
|
|
|
|
|
The rest of the merges did not add a merge commit, because there were no changes.
|
|
|
|
|
|
## How do we Create Backport Branches?
|
|
|
|
|
|
Use `git-merge-forward.sh -t bugNNNNN` to automatically create merge forward branches from the current contents of your maint-* and master working directories.
|
|
|
|
|
|
To make the merges as simple as possible, here's what we usually do:
|
|
|
* when we know we want to backport, we find the earliest maint branch (N) that needs a backport
|
|
|
* if we're writing the bugfix, we write the fix on branch N
|
|
|
* if we have a bugfix on master, we cherry-pick or rebase to N
|
|
|
* once the backport branch is done, we merge the branch into N, and then merge N+branch forward
|
|
|
* if there are any significant conflicts, we find the earliest maint branch with a conflict (M)
|
|
|
* we make a separate branch based on M that resolves the conflict (How? We still need to write a merge policy.)
|
|
|
* then we continue to merge forward
|
|
|
|
|
|
Even if there are no conflicts, the patch may require changes to work on later versions. We deal with these changes in a similar way:
|
|
|
* merge forward the changes for previous versions,
|
|
|
* add a commit with the new required changes, on the earliest maint branch that needs the change.
|
|
|
|
|
|
Just merge lines in merge commits. Don't put semantic changes in merge commits. Instead, put them in a new commit after the merge commit.
|
|
|
|
|
|
If we create merge branches this way, we should be able to merge all these branches in the right places, then merge forward without conflicts.
|
|
|
|
|
|
## TODO
|
|
|
|
|
|
We should integrate this document with the stable maintainer guide.
|
|
|
|
|
|
We should decide if we need more comprehensive instructions for unclean merge commits.
|
|
|
|
|
|
We should automate as much of this process as possible. |
|
|
\ No newline at end of file |