threads / discuss / 55666

Rebase Question

Subject: Rebase Question

## tl;dr

6 messages between May 12, 2021 and May 12, 2021.

replies: 5people: 6as markdown or json

Andrew Ottaviano· May 12, 2021, 00:06 UTC · lore
Hello all! 
 
I’ve used git for a few years now and I
think it is an amazing tool! Thank you for your hard work in
developing/maintaining it! I really appreciate it! 
 
I have a question. Let’s say that my
colleague and I branch off of master and are working. Let’s say I’m 5 commits
ahead of master and my colleague merges in ahead of me. The logical thing in my
mind is to rebase off of master. The difficulty with this is that if I have
merge conflicts that show up on my first commit, I have to resolve that stupid
thing for every subsequent commit. I could squash, but then I loose branch
history, so I don’t really want to do that. I could rebase in interactive mode,
but if I recall, I still need to resolve all the conflicts on every commit
before it squashes. 
 
The solution that I thought of is instead
of resolving conflicts from the bottom up (starting with earliest history),
resolving from the top down (latest to earliest) and resolving the conflict in
the commit it occurred. If that doesn’t work (or I guess it might be the same
as a merge of master into my branch), then couldn’t git at least store the
conflict resolution? 
 
Maybe I’m silly for asking this question,
I just really like rebase because it is so clean and this is my one frustration
with this method. 

Thanks for humoring me 😊  Andrew Ottaviano 

Jacob Keller· May 12, 2021, 00:23 UTC · re: Andrew Ottaviano · lore

Re: Rebase Question

On Tue, May 11, 2021 at 5:08 PM Andrew Ottaviano <andrew_o1995@live.com> wrote:
Show 23 quoted lines
>
> Hello all!
>
> I’ve used git for a few years now and I
> think it is an amazing tool! Thank you for your hard work in
> developing/maintaining it! I really appreciate it!
>
> I have a question. Let’s say that my
> colleague and I branch off of master and are working. Let’s say I’m 5 commits
> ahead of master and my colleague merges in ahead of me. The logical thing in my
> mind is to rebase off of master. The difficulty with this is that if I have
> merge conflicts that show up on my first commit, I have to resolve that stupid
> thing for every subsequent commit. I could squash, but then I loose branch
> history, so I don’t really want to do that. I could rebase in interactive mode,
> but if I recall, I still need to resolve all the conflicts on every commit
> before it squashes.
>
> The solution that I thought of is instead
> of resolving conflicts from the bottom up (starting with earliest history),
> resolving from the top down (latest to earliest) and resolving the conflict in
> the commit it occurred. If that doesn’t work (or I guess it might be the same
> as a merge of master into my branch), then couldn’t git at least store the
> conflict resolution?

You might try looking at git imerge for this https://github.com/mhagger/git-imerge

It resolves conflicts by doing incremental merges, and then you can have an option to produce the end result of a merge or a rebase.

Show 5 quoted lines
>
> Maybe I’m silly for asking this question,
> I just really like rebase because it is so clean and this is my one frustration
> with this method.
>

It's definitely a potential frustration that can occur during large rebases like this.

Thanks, Jake

>
> Thanks for humoring me
> Andrew Ottaviano
Bryan Turner· May 12, 2021, 00:29 UTC · re: Andrew Ottaviano · lore

Re: Rebase Question

On Tue, May 11, 2021 at 5:07 PM Andrew Ottaviano <andrew_o1995@live.com> wrote:
Show 16 quoted lines
>
> Hello all!
>
> I’ve used git for a few years now and I
> think it is an amazing tool! Thank you for your hard work in
> developing/maintaining it! I really appreciate it!
>
> I have a question. Let’s say that my
> colleague and I branch off of master and are working. Let’s say I’m 5 commits
> ahead of master and my colleague merges in ahead of me. The logical thing in my
> mind is to rebase off of master. The difficulty with this is that if I have
> merge conflicts that show up on my first commit, I have to resolve that stupid
> thing for every subsequent commit. I could squash, but then I loose branch
> history, so I don’t really want to do that. I could rebase in interactive mode,
> but if I recall, I still need to resolve all the conflicts on every commit
> before it squashes.

Have you investigated git rerere[1] at all? Documentation indicates it works for rebase as well as merge, so it might be possible to train that to resolve the conflicts.

[1] https://git-scm.com/docs/git-rerere
(Pardon the re-send; Gmail being trash.)
Jeff King· May 12, 2021, 00:44 UTC · re: Bryan Turner · lore

Re: Rebase Question

On Tue, May 11, 2021 at 05:29:03PM -0700, Bryan Turner wrote:
Show 21 quoted lines
> On Tue, May 11, 2021 at 5:07 PM Andrew Ottaviano <andrew_o1995@live.com> wrote:
> >
> > Hello all!
> >
> > I’ve used git for a few years now and I
> > think it is an amazing tool! Thank you for your hard work in
> > developing/maintaining it! I really appreciate it!
> >
> > I have a question. Let’s say that my
> > colleague and I branch off of master and are working. Let’s say I’m 5 commits
> > ahead of master and my colleague merges in ahead of me. The logical thing in my
> > mind is to rebase off of master. The difficulty with this is that if I have
> > merge conflicts that show up on my first commit, I have to resolve that stupid
> > thing for every subsequent commit. I could squash, but then I loose branch
> > history, so I don’t really want to do that. I could rebase in interactive mode,
> > but if I recall, I still need to resolve all the conflicts on every commit
> > before it squashes.
> 
> Have you investigated git rerere[1] at all? Documentation indicates it
> works for rebase as well as merge, so it might be possible to train
> that to resolve the conflicts.

I don't think rerere helps here. In a rebase like this, the problem is that it _isn't_ the same conflict.

Imagine a case like this:

-- >8 -- git init repo cd repo

# both branches start with just the line "base" echo base >file git add file git commit -m base

# one side adds a new line git checkout -b newline echo another >>file git commit -am 'add a line'

# and the other modifies the first line git checkout -b other HEAD^ echo one >file git commit -am one echo two >file git commit -am two

# and now we rebase on top of the newline branch git rebase newline -- >8 --

Applying the first commit gets this conflict (in diff3 form)
  <<<<<<< ours
  base
  another
  ||||||| base
  base
  =======
  one
  >>>>>>> theirs
After we fix that up to "one\nanother", the second conflict is:
  <<<<<<< ours
  one
  another
  ||||||| base
  one
  =======
  two
  >>>>>>> theirs

Likewise, even if you had done the original merge between branch tips, you'd have seen yet another conflict:

  <<<<<<< ours
  two
  ||||||| base
  base
  =======
  base
  another
  >>>>>>> theirs

The actual lines changed are the same, but as the nearby context is continually shifting, we don't consider these to be the "same" conflict.

-Peff
Junio C Hamano· May 12, 2021, 06:22 UTC · re: Jeff King · lore

Re: Rebase Question

Jeff King <peff@peff.net> writes:
Show 41 quoted lines
> I don't think rerere helps here. In a rebase like this, the problem is
> that it _isn't_ the same conflict.
>
> Imagine a case like this:
> ...
> Applying the first commit gets this conflict (in diff3 form)
>
>   <<<<<<< ours
>   base
>   another
>   ||||||| base
>   base
>   =======
>   one
>   >>>>>>> theirs
>
> After we fix that up to "one\nanother", the second conflict is:
>
>   <<<<<<< ours
>   one
>   another
>   ||||||| base
>   one
>   =======
>   two
>   >>>>>>> theirs
>
> Likewise, even if you had done the original merge between branch tips,
> you'd have seen yet another conflict:
>
>   <<<<<<< ours
>   two
>   ||||||| base
>   base
>   =======
>   base
>   another
>   >>>>>>> theirs
>
> The actual lines changed are the same, but as the nearby context is
> continually shifting, we don't consider these to be the "same" conflict.

Correct. The conflict you see at each step may be trivial to resolve, but would not "replay" at all, exactly because they are not the same conflicts. Knowing that the user would resolve

    base --> base/another
        \                \
         ---> one--------- one/another
does not help us to decide that
    base --> two -----------
        \                   \
         ---> base/another---???
is resolved to two/another.
Felipe Contreras· May 12, 2021, 07:23 UTC · re: Andrew Ottaviano · lore

RE: Rebase Question

Andrew Ottaviano wrote:
> The difficulty with this is that if I have merge conflicts that show
> up on my first commit, I have to resolve that stupid thing for every
> subsequent commit.

I don't quite understand that. If you have resolved the chunk, then that chunk is resolved, and the rest of the commits don't have to worry about that...

Unless they touch *precisely* the same lines as the first commit, in which case... Yeah, you have to resolve that stupid thing over and over.

> The solution that I thought of is instead of resolving conflicts from
> the bottom up (starting with earliest history), resolving from the top
> down (latest to earliest) and resolving the conflict in the commit it
> occurred.

Well, this is interesting because it's something I've wanted to write about for a long time, and it's what I call my "pronged approach".

I actually do *both*; I do a rebase and fix the problems from 1) the bottom-up, but after I have resolved the conflicts from 2) the top-down. In 1) (bottom-up) I resolve the conflicts in a rebase, and in 2) I resolve the conflicts in merge, but in *both* the end result sould be the exactly same [`git diff 1) 2)` is empty].

Yes, it is more work, but at the end of the day I'm 100% sure I did the rebase right, so I don't have to think about it that much; either there's a diff or there isn't.

In fact, I rarely do just one rebase, because quite often I miss things, so I do a second, or third, or fourth rebase, but at the end I make sure that the diff with the merge (top-down approach) is the same.

To facilitate this work I use two tools: 1) git rerere [1] (others have mentioned this), and 2) git reintegrate [2] (only useful if there's more than one branch you are merging).

Yeah, it's a lot of work, but I'd rather do a lot of tedious work that I'm 100% sure is correct, than do a little bit of work that I can't easily verify.

Cheers.

[1] https://git-scm.com/docs/git-rerere [2] https://github.com/felipec/git-reintegrate

-- 
Felipe Contreras

← back to recent threads