- Justification
- Precis
- Other implementations
- Implementation details
- Use-case / story
- Alice has been working on a feature and is ready to submit a pull request
- Bob, owner of the project Alice sent the pull-request to, receives the request
- Alice, author of the pull-request, gets notified that Bob updated it
- Bob receives the updated pull-request notification
- Alice gets a notification that her pull-request was updated.
Justification
Currently pull requests are managed on mailing lists etc and while this is fine it doesn't fit with the disconnected/distributed development model which Git promotes. We are looking to provide a mechanism to manage pull requests, allowing the core discussion to continue in whatever medium the project prefers but storing the salient points into Git, allowing for offline activity.
Precis
The idea of git pull-request
is to provide an in-git mechanism to record the
conversation between a patch author and a core developer while looking at a
patch provided for merging. The conversation might include submitting
particular commits for merging, or providing feedback on those commits. It
also might involve arbitrary information passing in either direction.
Other implementations
Github and Gitorious both have pull-requests built into them. Both use a bit
of the Git ref namespace. Github seems to use refs/pull/<nnn>/{head,merge}
where Gitorious uses refs/merge-requests/<nnn>
. Both these implementations
are only using the refs to indicate the actual commit-line to be merged.
Neither of them seem to store any metadata about the pull-request in Git.
Thus, to manipulate pull requests (beyond test-merging them) you need access to
the Github or Gitorious server.
Gitolite carries a contrib adc called hub
which implements pull requests.
You must be connected to the server in order to use the hub
tool and while
the hub
means you don't have to fetch the implementations of pull-requests
local, it still doesn't store the data in the Git repository itself.
Implementation details
Each pull-request consists of two important parts. The first is a line of
commits which are being considered for merging. The second is a line of
discussion about the merge. Each of those can be represented as a ref. The
commit itself could be in refs/heads/
and the meta-information under
refs/pull-requests/heads/
.
Using the refs/pull-requests/heads/
prefix for access control
Since projects tend to use git servers (such as Gitano) to perform access
control, we want git pull-request
to be able to satisfy those kinds of
access controls. As such, we will support the ref-to-be-merged being
stored under refs/pull-requests/heads/
alongside the meta ref.
Naming refs for pull requests.
In order to increase the efficiency of pull requests while still allowing all
of the history to be stored if desired, pull requests will be also use an
additional refs namespace, namely refs/pull-requests/archived/
which
will only contain pull requests considered to be archived. By default git
pull-request
will not interact with these refs (except to archive finished
pull requests on demand).
Pull requests already present in remotes.
In order to work effectively with git remotes (and thus work with others) the
git pull-request
system places remote requests under
refs/pull-requests/remotes/<remotename>/heads/
and
refs/pull-requests/remotes/<remotename>/archived/
. The git pull-request
script can automatically add appropriate fetch rules to remotes and/or control
the fetching/pushing itself via git pull-request sync
or similar.
Use-case / story
Alice has been working on a feature and is ready to submit a pull request
The work Alice has been doing is currently in her repository in her working
branch. She's ready to submit it for pulling into the project's master
branch which is where that project accepts submissions for the next release.
She runs git pull-request create alice/magical-unicorns
and then feeds a
precis into the editor which appears. This results in two refs being created:
refs/pull-requests/heads/alice/magical-unicorns
and
refs/pull-requests/heads/alice/magical-unicorn__anchor
the former of which
contains the metadata about the request and the latter is an anchor for the
commit being requested for pull.
She already has the project's remote setup as origin
and has permissions to
send pull requests directly using her username as a prefix (hence she used
alice/
in naming her pull request). She simply runs git pull-request sync
and thanks to the fact that her branch was already tracking origin/master
the
tool knows where to send the pull request which is does using git push and some
appropriate refspecs.
Bob, owner of the project Alice sent the pull-request to, receives the request
Bob, being ready and willing to accept pull requests, has been notified about
Alice's pull request. Perhaps this is via a mailing list thread or perhaps by
some magic to do with the server he's using to host his project. Either way he
runs git pull-request sync
and gets notified of the new pull request.
To learn about the pull request, Bob runs git pull-request precis
alice/magical-unicorns
which prints to his terminal the content of the precis
of the pull request.
Having decided that Alice's idea is good, he wants to review the code. First
he thinks he should look at the commits in isolation so he runs git
pull-request log alice/magical-unicorns
and is presented with the log for
Alice's work (Note, not the log of the pull-request itself, for that he'd have
to run git pull-request request-log alice/magical-unicorns
instead.)
Bob then runs git pull-request merge alice/magical/unicorns
and is told that
his currently checked out branch is not suitable for landing the request.
Feeling sheepish he switches from a feature-branch he's working on to the
master and re-runs the merge command. This time the merge is okay and he's
left with his working tree having had the merge done and he can run git diff
--cached
to look at the diff and obviously he can build and test Alice's
contribution. When he's finished he can either git commit
the work if he
likes it, or git reset --hard HEAD
to remove the changes if he doesn't.
If Bob has committed the merge, providing it was merged to the branch which it
was originally intended to be landed, git pull-request sync
will notice and
complete the pull request, automatically archiving it and pushing the info to
the remote server. If he merged it into somewhere else, he has the option of
saying git pull-request merged alice/magical-unicorns
which causes the branch
onto which the pull request was actually merged to be recorded ready for the
next time he synchronises. He may also git pull-request archive
alice/magical-unicorns
if he does not wish to wait until the branch lands on
the original target before it is archived.
If, on the other hand, Bob decided not to merge Alice's work, he may choose to
comment on it instead. He might run git pull-request needs-work
alice/magical-unicorns
and enter his comments into the editor which appears.
If he wants to attach extra stuff he might run git pull-request attach
alice/magical-unicorns some/files...
which will allow him to add content to
the pull-request which Alice can retrieve later. Once he's satisfied he's
said/attached all that he needs to, Bob runs git pull-request sync
to ensure
that the updated pull requests are sent to the server for Alice to see later.
Alice, author of the pull-request, gets notified that Bob updated it
Alice first runs git pull-request sync
which updates her with Bob's notes.
She runs git pull-request status alice/magical-unicorns
and sees that Bob
marked it as needs-work. She runs git pull-request request-log
alice/magical-unicorns
and notes that Bob has attached some files and made
various comments. about stuff she did.
Bob had suggested another test case which he invented which matched Alice's
specification but did not pass. She runs git pull-request get
alice/magical-unicorns bob/test-case
and integrates the test case into her
branch, making the fixes necessary to ensure that it works.
She commits that work and then runs git pull-request resubmit
alice/magical-unicorns
followed by git pull-request sync
to re-send the
request to Bob.
Bob receives the updated pull-request notification
Bob runs git pull-request sync
and then since he knows what he needs to look
for, he runs git pull-request log alice/magical-unicorns -p
and reads the
extra commits Alice made since the last time he reviewed the branch.
Bob, deciding that the code and test cases all look good, then merges the code
with git pull-request merge alice/magical-unicorns
, runs one final set of
tests and then runs git commit
. Finally he runs git pull-request sync
.
The sync process notes that Alice's branch has been landed, updates it to
indicate how/where and moves it to the archive, before pushing the ref updates
to Bob's server.
Alice gets a notification that her pull-request was updated.
Alice runs git pull-request sync
and gets informed that
alice/magical-unicorns
was archived as merged. She, rather deservedly, has a
celebratory drink.