I will take this opportunity to pimp the video series I did on this exact topic: https://www.youtube.com/watch?v=mHyvP7zp4Ko&list=PLR97FKPZ-mD9XJCfwDE5c-td9lZGIPfS5&index=4 On 12/5/18 11:18 AM, Eric Fried wrote:
This started off as a response to some questions Sundar asked, but I thought it might be interesting/useful for new[er] OpenStack developers at large, so broadcasting.
I'm sure there's a document somewhere that covers this, but here's a quick run-down on how to develop multiple changes in a series. (Or at least, how I do it.)
Start on a freshly-pull'd master branch:
efried@efried-ThinkPad-W520:~/Neo/nova$ git checkout master Switched to branch 'master' Your branch is up-to-date with 'origin/master'. efried@efried-ThinkPad-W520:~/Neo/nova$ git pull --all <snip>
When you're working on a blueprint, you want to name your local branch after the blueprint. So in this case, bp/nova-cyborg-interaction.
efried@efried-ThinkPad-W520:~/Neo/nova$ git checkout -b bp/nova-cyborg-interaction Switched to a new branch 'bp/nova-cyborg-interaction' efried@efried-ThinkPad-W520:~/Neo/nova$ git log --oneline -1 --decorate 5bf6f63 (HEAD, origin/master, origin/HEAD, gerrit/master, master, bp/nova-cyborg-interaction) Merge "Deprecate the nova-xvpvncproxy service"
When you `git commit` (without `--amend`), you're creating a new commit on top of whatever commit you started at. If you started with a clean, freshly pull'd master branch, that'll be whatever the most recently merged commit in the master branch was. In this example, that's commit 5bf6f63.
So let's say I make an edit for my first patch and commit it:
efried@efried-ThinkPad-W520:~/Neo/nova$ echo 'python-cyborgclient>=1.0'
requirements.txt efried@efried-ThinkPad-W520:~/Neo/nova$ echo 'python-cyborgclient==1.1' lower-constraints.txt efried@efried-ThinkPad-W520:~/Neo/nova$ git commit -a -m "Add cyborg client to requirements" [bp/nova-cyborg-interaction 1b2c453] Add cyborg client to requirements 2 files changed, 2 insertions(+) efried@efried-ThinkPad-W520:~/Neo/nova$ git log --oneline -2 --decorate 1b2c453 (HEAD, bp/nova-cyborg-interaction) Add cyborg client to requirements 5bf6f63 (origin/master, origin/HEAD, gerrit/master, master) Merge "Deprecate the nova-xvpvncproxy service"
I just made commit 1b2c453 on top of 5bf6f63. You'll notice my branch name (bp/nova-cyborg-interaction) came along with me.
Now I'm going to make another change, but just part of it, a work-in-progress commit:
efried@efried-ThinkPad-W520:~/Neo/nova$ mkdir nova/pci/cyborg efried@efried-ThinkPad-W520:~/Neo/nova$ touch nova/pci/cyborg/__init__.py efried@efried-ThinkPad-W520:~/Neo/nova$ git add nova/pci/cyborg/__init__.py efried@efried-ThinkPad-W520:~/Neo/nova$ git commit -m "WIP: Cyborg PCI handling" [bp/nova-cyborg-interaction ebb3505] WIP: Cyborg PCI handling 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 nova/pci/cyborg/__init__.py efried@efried-ThinkPad-W520:~/Neo/nova$ git log --oneline -3 --decorate ebb3505 (HEAD, bp/nova-cyborg-interaction) WIP: Cyborg PCI handling 1b2c453 Add cyborg client to requirements 5bf6f63 (origin/master, origin/HEAD, gerrit/master, master) Merge "Deprecate the nova-xvpvncproxy service"
Now commit ebb3505 is on top of 1b2c453, which is still on top of 5bf6f63 (the master). Note that my branch name came with me again.
At this point, I push my series up to gerrit. Note that it makes me confirm that I really want to push two commits at once.
efried@efried-ThinkPad-W520:~/Neo/nova$ git review You are about to submit multiple commits. This is expected if you are submitting a commit that is dependent on one or more in-review commits, or if you are submitting multiple self-contained but dependent changes. Otherwise you should consider squashing your changes into one commit before submitting (for indivisible changes) or submitting from separate branches (for independent changes).
The outstanding commits are:
ebb3505 (HEAD, bp/nova-cyborg-interaction) WIP: Cyborg PCI handling 1b2c453 Add cyborg client to requirements
Do you really want to submit the above commits? Type 'yes' to confirm, other to cancel: yes remote: remote: Processing changes: new: 2, refs: 2 (\) remote: Processing changes: new: 2, refs: 2 (\) remote: Processing changes: new: 2, refs: 2 (\) remote: Processing changes: new: 2, refs: 2, done remote: remote: New Changes: remote: https://review.openstack.org/623026 Add cyborg client to requirements remote: https://review.openstack.org/623027 WIP: Cyborg PCI handling remote: To ssh://efried@review.openstack.org:29418/openstack/nova.git * [new branch] HEAD -> refs/publish/master/bp/nova-cyborg-interaction
Now if you go to either of those links - e.g. https://review.openstack.org/#/c/623026/ - you'll see that the patches are stacked up in series on the top right.
But oops, I made a mistake in my first commit. My lower constraint can't be higher than my minimum in requirements.txt. If I still had my branch locally, I could skip this next step, but as a matter of rigor to avoid some common pratfalls, I will pull the whole series afresh from gerrit by asking git review to grab the *top* change:
efried@efried-ThinkPad-W520:~/Neo/nova$ git review -d 623027 Downloading refs/changes/27/623027/1 from gerrit Switched to branch "review/eric_fried/bp/nova-cyborg-interaction"
Now I'm sitting on the top change (which you'll notice happens to be exactly the same as before I pushed it - again, meaning I could technically have just worked from where I was, but see above):
efried@efried-ThinkPad-W520:~/Neo/nova$ git log --oneline -3 --decorate ebb3505 (HEAD, review/eric_fried/bp/nova-cyborg-interaction, bp/nova-cyborg-interaction) WIP: Cyborg PCI handling 1b2c453 Add cyborg client to requirements 5bf6f63 (origin/master, origin/HEAD, gerrit/master, master) Merge "Deprecate the nova-xvpvncproxy service"
But I want to edit 1b2c453, while leaving ebb3505 properly stacked on top of it. Here I use a tool called `git restack` (run `pip install git-restack` to install it).
efried@efried-ThinkPad-W520:~/Neo/nova$ git restack
This pops me into an editor showing me all the commits between wherever I am and the main branch (now they're in top-first order):
pick 1b2c453 Add cyborg client to requirements pick ebb3505 WIP: Cyborg PCI handling <snip>
I want to fix the first one, so I change to:
edit 1b2c453 Add cyborg client to requirements pick ebb3505 WIP: Cyborg PCI handling <snip>
Save and quit the editor, and I see:
Stopped at 1b2c453453242a3fa57f2d4fdc80c837b02b804f... Add cyborg client to requirements You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
I fix lower-constraints:
efried@efried-ThinkPad-W520:~/Neo/nova$ sed -i 's/cyborgclient==1.1/cyborgclient==1.0/' lower-constraints.txt
...and *amend* the current commit
efried@efried-ThinkPad-W520:~/Neo/nova$ git commit -a --amend --no-edit [detached HEAD 6b3455f] Add cyborg client to requirements Date: Wed Dec 5 09:43:15 2018 -0600 2 files changed, 2 insertions(+)
...and tell `git restack` to proceed
efried@efried-ThinkPad-W520:~/Neo/nova$ git rebase --continue Successfully rebased and updated refs/heads/review/eric_fried/bp/nova-cyborg-interaction.
If I had a taller series, and I had changed 'pick' to 'edit' for more than one commit, I would now be sitting on the next one I needed to edit. As it is, that was the only thing I needed to do, so I'm done and sitting on the top of my series again.
124b612 (HEAD, review/eric_fried/bp/nova-cyborg-interaction) WIP: Cyborg PCI handling 6b3455f Add cyborg client to requirements 5bf6f63 (origin/master, origin/HEAD, gerrit/master, master) Merge "Deprecate the nova-xvpvncproxy service"
Notice that the commit hashes have changed for *both* commits (but not the master). The top one changed because it got rebased onto the new version of the middle one.
Now if I push the series back up to gerrit, I get the same confirmation prompt, and both changes get a new patch set. If you look at the top patch in gerrit, you'll see that PS2 shows up as just a rebase.
====================
That ought to be enough for now. There's a couple of gotchas when restacking and the automatic rebase results in merge conflicts, but we can save that for another time.
To answer your specific question:
* If you have a patch sequence A followed by B, where patch B depends on patch A, how do you communicate that in the submission?
If they're in the same commit series, like the example above, It Just Happens. Zuul and the CIs know to pull the whole series when they run; gerrit won't merge N+1 until N is merged; etc.
If they're *not* in the same commit series, or if they're not in the same repository, you can use Depends-On in the commit message, to the same effect. (But I'm not sure if/how Depends-On works for feature branches.)
HTH, efried .