How to 'rebase the change locally'?

4,336 views
Skip to first unread message

Eric Tsai

unread,
Mar 24, 2009, 8:41:52 AM3/24/09
to Repo and Gerrit Discussion
Situation:
Change 2 owned by user 1 depends on change 1. Change 3 owned by user 2
also depends on change 1.
I approv change 2 and click 'Submit Patch Set 1', it merges
successfully.
Then I approve change change 3 and click 'Submit Patch Set 1', I got:
"Your change could not be merged due to path conflict. Please merge
(or rebase) the change locally and upload the resolution for review."


My current action:
On user 2's machine, I do 'git pull', solve conflicts, commit, push to
Gerrit (create change 4 for merge). Then I can approve change 3 and 4.

What I want to achieve:
'git pull' then 'git push' will create an additional change for the
commit on Gerrit.
If I can do a rebase based on the repository version which already
have change 2 merged, then I can summit the change again on user2's
machine to replace the old change 3 on Gerrit.
But how do I achieve this by git commands? (sorry I'm not familiar
with git commands)

Jean-Baptiste Queru

unread,
Mar 24, 2009, 10:43:51 AM3/24/09
to repo-d...@googlegroups.com
If you're working on single changes (as opposed to uploading chains of
changes), you can work that way:

repo start a new topic branch
repo sync
repo download your change (if you don't already have it on that client)
git cherry-pick <SHA-1 of your original change>
repo upload --replace
verify/approve/submit.

JBQ
--
Jean-Baptiste M. "JBQ" Queru
Android Engineer, Google.

Questions sent directly to me that have no reason for being private
will likely get ignored or forwarded to a public forum with no further
warning.

Eric Tsai

unread,
Mar 24, 2009, 11:22:28 AM3/24/09
to Repo and Gerrit Discussion
I've tried the following commands on user2's machine:
==================================
git checkout -b test origin/master (now there are 2 branches: master &
tset on user1's machine)
git pull ssh://localhost:29418/git_test refs/changes/02/2/1
git cherry-pick <SHA-1 of change 3>
vi test.c, fix the conflict
git add test.c
git commit
git push ssh://localhost:29418/git_test HEAD:refs/changes/3
==================================
Now I can verify/approve/submit the new change 3. Are these right?

But when I go back to my original branch (git checkout master) which
already have the old change 3 on user2's machine then do 'git pull' to
update,
I got conflicts with new change 3.
What command should I use to have a successful pull?
> warning.- Hide quoted text -
>
> - Show quoted text -

Jean-Baptiste Queru

unread,
Mar 24, 2009, 11:53:30 AM3/24/09
to repo-d...@googlegroups.com
Your commands look right so far, but someone with more git expertise
should confirm.

What's happening now is that your last git pull tries to merge the
"new" (cherry-picked) change3 (which comes from the server) against
the "old" one that exists in user2's master branch.

If I'm not mistaken, the solution is to move user2's master branch
back to a point where it didn't have change3 (but still had change2),
and to pull at that point.

Be sure that you're on the master branch at that point, and I think
the command should be "git reset --hard HEAD^" - though it'd be
helpful if someone confirmed before you did anything wrong there.

JBQ

Eric Tsai

unread,
Mar 24, 2009, 12:23:39 PM3/24/09
to Repo and Gerrit Discussion
Thanks, JBQ. It works. :D

Zach Wily

unread,
Mar 24, 2009, 9:19:45 AM3/24/09
to repo-d...@googlegroups.com
> Situation:
> Change 2 owned by user 1 depends on change 1. Change 3 owned by user 2
> also depends on change 1.
> I approv change 2 and click 'Submit Patch Set 1', it merges
> successfully.
> Then I approve change change 3 and click 'Submit Patch Set 1', I got:
> "Your change could not be merged due to path conflict. Please merge
> (or rebase) the change locally and upload the resolution for review."
>
>
> My current action:
> On user 2's machine, I do 'git pull', solve conflicts, commit, push to
> Gerrit (create change 4 for merge). Then I can approve change 3 and 4.

Do 'git pull --rebase' to rebase change 3 on top of change 2. Resolve
conflicts, then 'git push origin HEAD:refs/changes/3' to update the
existing change for 3 to the new rebased version. Then it can be
approved and merged.

zach

Eric Tsai

unread,
Mar 24, 2009, 7:15:33 PM3/24/09
to Repo and Gerrit Discussion
Thanks, Zach. This is a concise solution.
> > with git commands)- Hide quoted text -

Eric Tsai

unread,
Mar 25, 2009, 2:53:35 AM3/25/09
to Repo and Gerrit Discussion
I run 'gitk --all' in kernel/common.git and find that the commit log
of the project are make up with several straight lines. A stright line
usually means several commits with different authors by a same
committer.
I think if the source code is contributed by people all around the
world, the 'gitk -all' output should have lots of branches like my
example (1->2, 1->3). How could it be so beautiful (1->2->3)?

If I want it to look like a stright line, the commiter has to download
a new change (says B) he/she wants to commit, and rebase it on the
previous change the comiiter just commits (says A) to get B'. Then
replace B by B' on Gerrit in order not to create an additional change.
This is so inconvenient.

Another way I can think of is the comitter tells the author of B to
rebase its change on A to get B' then send B' to Gerrit again to
replace B. Same thing has to be done for change C, D, E, etc. This
seems impossible. How could a commiter reach an author everytime he/
she want's to commit a change?

How does the real world work?

David Brown

unread,
Mar 25, 2009, 11:58:27 AM3/25/09
to repo-d...@googlegroups.com
On Tue, Mar 24, 2009 at 11:53 PM, Eric Tsai <erict...@gmail.com> wrote:

Another way I can think of is the comitter tells the author of B to
rebase its change on A to get B'  then send B' to Gerrit again to
replace B. Same thing has to be done for change C, D, E, etc. This
seems impossible. How could a commiter reach an author everytime he/
she want's to commit a change?

How does the real world work?

Try  'git log --pretty=fuller'.  You'll find that in the kernel history, many commits get rebased by someone other than the author.  There are a lot of people that clean up history lines before it gets to the mainline. It's a somewhat different workflow than Gerrit uses.

David

Eric Tsai

unread,
Mar 25, 2009, 12:46:16 PM3/25/09
to Repo and Gerrit Discussion
Hi David,

The info provided by 'git log --pretty=fuller' looks the same as using
'gitk --all'.
I think I don't get your point. I know it seems like a few comitters
have to rebase changes from a lot of authors.

Since we can see changes for kernel/common at
https://review.source.android.com/Gerrit#all,open,n,z
That means changes for the kernel still been controlled by Gerrit,
right?
What extra efforts does the maintainer of the history have to do to
make the history a straight line with only few branches/merges?
If a comitter does the rebase of a change and replace it on Gerrit, I
should see there is at least 'Patch Set 2' for a change because it has
been replaced.
But I dont's see this phenomenon. So where do the rebases been done?
Could you please give me a simple example?

Thank you very much.

Shawn Pearce

unread,
Mar 25, 2009, 12:58:15 PM3/25/09
to repo-d...@googlegroups.com
2009/3/25 Eric Tsai <erict...@gmail.com>:

> Since we can see changes for kernel/common at
> https://review.source.android.com/Gerrit#all,open,n,z
> That means changes for the kernel still been controlled by Gerrit,
> right?

Yes, and no. The kernel developers are experienced Git users and
sometimes bypass the code review feature and push directly into the
branch. They tend to do that by downloading changes from other
authors, rebasing them into a nice history, testing that code, and
then pushing it directly into the branch.

There are several open feature requests from the kernel developers to
help them smooth this workflow out. Not all of them have made it into
JIRA yet, but have been on the table for months, perhaps since before
AOSP even was announced to the public.

> What extra efforts does the maintainer of the history have to do to
> make the history a straight line with only few branches/merges?

Yea, you need to do the rebase for the developer to submitting it.
The kernel folks often rebase before they upload, and then submit
immediately after uploading, so that they get a nice history.

There is an open feature request to permit Gerrit to do some trivial
rebases in the server automatically, rather than creating a merge.
Its pretty much the same idea, but the trivial rebase discards the
parent information. Its a trade-off for the project owner to make;
keep more accurate development history, or keep a nice straight line
in their history.

Zach Wily

unread,
Mar 25, 2009, 3:33:47 PM3/25/09
to Repo and Gerrit Discussion
Is there any way to have Gerrit force authors to rebase their changes
against the current head before it will perform the merge? In other
words, I want all of the merges done by Gerrit to be fast-forward, and
make the user resubmit it if it's not. I have a small development team
that would like the more linear history, and we'd like Gerrit to help
enforce it if possible.

zach


On Mar 25, 10:58 am, Shawn Pearce <s...@google.com> wrote:
> 2009/3/25 Eric Tsai <erictsa...@gmail.com>:

Shawn Pearce

unread,
Mar 25, 2009, 3:40:11 PM3/25/09
to repo-d...@googlegroups.com
On Wed, Mar 25, 2009 at 12:33, Zach Wily <za...@zwily.com> wrote:
>
> Is there any way to have Gerrit force authors to rebase their changes
> against the current head before it will perform the merge? In other
> words, I want all of the merges done by Gerrit to be fast-forward, and
> make the user resubmit it if it's not. I have a small development team
> that would like the more linear history, and we'd like Gerrit to help
> enforce it if possible.

Yes, there is a hidden flag. Set a config option in the repository:

git --git-dir=project.git config gerrit.fastforwardonly true

and restart Gerrit.

I was planning on moving this into the database and making it a
checkbox in the web UI this week. Its an old hack from Gerrit 1.x
that got carried into Gerrit 2.x (MergeOp.java is about the only code
that survived intact during the rewrite). This should be a UI level
feature for the project owner, not some hidden thing in the project's
GIT_DIR/config.

After its in the web UI I'll mention it in the release notes, and
probably have a Java tool to help you convert the config file setting
into the database since I need that for r.s.a.c anyway.

Zach Wily

unread,
Mar 25, 2009, 4:00:23 PM3/25/09
to Repo and Gerrit Discussion
> Yes, there is a hidden flag.  Set a config option in the repository:
>
>   git --git-dir=project.git config gerrit.fastforwardonly true
>
> and restart Gerrit.

Excellent! Thank you.

> I was planning on moving this into the database and making it a
> checkbox in the web UI this week.  Its an old hack from Gerrit 1.x
> that got carried into Gerrit 2.x (MergeOp.java is about the only code
> that survived intact during the rewrite).  This should be a UI level
> feature for the project owner, not some hidden thing in the project's
> GIT_DIR/config.
>
> After its in the web UI I'll mention it in the release notes, and
> probably have a Java tool to help you convert the config file setting
> into the database since I need that for r.s.a.c anyway.

Sounds great.

zach

Eric Tsai

unread,
May 15, 2009, 11:46:18 AM5/15/09
to Repo and Gerrit Discussion
It seems currently each "Change Submit Action" will result in one
single last commit in the history.
Gerrit doesn't allow multiple path (e.g. multiple straight line in
kernel/common.git) like normal git repository does, right?

On 3月26日, 上午3時40分, Shawn Pearce <s...@google.com> wrote:

Shawn Pearce

unread,
May 15, 2009, 12:16:22 PM5/15/09
to repo-d...@googlegroups.com
2009/5/15 Eric Tsai <erict...@gmail.com>


It seems currently each "Change Submit Action" will result in one
single last commit in the history.
Gerrit doesn't allow multiple path (e.g. multiple straight line in
kernel/common.git) like normal git repository does, right?

I don't understand the question.  What are you trying to ask?

Eric Tsai

unread,
May 15, 2009, 12:46:00 PM5/15/09
to Repo and Gerrit Discussion
Commit history of Git:
-------------------------------------------
push a:
a
-------------------------------------------
push b:
a -> b
-------------------------------------------
push c:
a -> b -> c
-------------------------------------------
push d:
- d
/
a -> b -> c
-------------------------------------------
push e:
- d -> e
/
a -> b -> c
-------------------------------------------
merge:
- d -> e
/ \
a -> b -> c -> merge c&e
-------------------------------------------
push f:
- d -> e
/ \
a -> b -> c -> merge c&e -> f



Commit history of Gerrit using "Merge If Necessary":
-------------------------------------------
upload, submit a:
a
-------------------------------------------
upload, submit b:
a -> b
-------------------------------------------
upload, submit c:
a -> b -> c
-------------------------------------------
upload d:
- d
/
a -> b -> c

submit d:
------> d
/ \
a -> b -> c -> merge c&d
-------------------------------------------
upload e:
------> d ----------> e
/ \
a -> b -> c -> merge d

submit e:
------> d ----------> e
/ \ \
a -> b -> c -> merge d -> merge e
-------------------------------------------
upload, submit f:
------> d ----------> e
/ \ \
a -> b -> c -> merge d -> merge e -> f

On 5月16日, 上午12時16分, Shawn Pearce <s...@google.com> wrote:
> 2009/5/15 Eric Tsai <erictsa...@gmail.com>

Eric Tsai

unread,
May 15, 2009, 12:50:30 PM5/15/09
to Repo and Gerrit Discussion
That is, commit history of Gerrit must converge, but commit history of
Git can be divergent.
> > I don't understand the question. What are you trying to ask?- 隱藏被引用文字 -
>
> - 顯示被引用文字 -

Shawn Pearce

unread,
May 15, 2009, 1:02:45 PM5/15/09
to repo-d...@googlegroups.com
Well, in your git example, when you pushed d and e, you must have pushed those to temporary branches.

To make Gerrit produce a DAG like Git would when you merge e, submit backwards:

submit e; blocks waiting for d.
submit d; submit of both finishes, and graph looks like git example graph.


2009/5/15 Eric Tsai <erict...@gmail.com>

Eric Tsai

unread,
May 15, 2009, 1:50:05 PM5/15/09
to Repo and Gerrit Discussion
Ahhh...I forgot I have created new branch for d and e.
Thanks.

On 5月16日, 上午1時02分, Shawn Pearce <s...@google.com> wrote:
> Well, in your git example, when you pushed d and e, you must have pushed
> those to temporary branches.
>
> To make Gerrit produce a DAG like Git would when you merge e, submit
> backwards:
>
> submit e; blocks waiting for d.
> submit d; submit of both finishes, and graph looks like git example graph.
>
> 2009/5/15 Eric Tsai <erictsa...@gmail.com>
> > > - 顯示被引用文字 -- 隱藏被引用文字 -
>
> - 顯示被引用文字 -
Reply all
Reply to author
Forward
0 new messages