[dev] How to develop changes in a series

Eric Fried openstack at fried.cc
Wed Dec 5 17:18:37 UTC 2018


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 at efried-ThinkPad-W520:~/Neo/nova$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
efried at 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 at efried-ThinkPad-W520:~/Neo/nova$ git checkout -b
bp/nova-cyborg-interaction
Switched to a new branch 'bp/nova-cyborg-interaction'
efried at 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 at efried-ThinkPad-W520:~/Neo/nova$ echo 'python-cyborgclient>=1.0'
>> requirements.txt
efried at efried-ThinkPad-W520:~/Neo/nova$ echo 'python-cyborgclient==1.1'
>> lower-constraints.txt
efried at 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 at 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 at efried-ThinkPad-W520:~/Neo/nova$ mkdir nova/pci/cyborg
efried at efried-ThinkPad-W520:~/Neo/nova$ touch nova/pci/cyborg/__init__.py
efried at efried-ThinkPad-W520:~/Neo/nova$ git add nova/pci/cyborg/__init__.py
efried at 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 at 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 at 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 at 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 at 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 at 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 at efried-ThinkPad-W520:~/Neo/nova$ sed -i
's/cyborgclient==1.1/cyborgclient==1.0/' lower-constraints.txt

...and *amend* the current commit

efried at 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 at 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
.




More information about the openstack-discuss mailing list