21 comments

[ 2.7 ms ] story [ 58.3 ms ] thread
can you do it as a git alias or a binary you can install as git-freebase?
I'm working on a bash script now. If it gets popular maybe it will make it into git flow, or tig, or even git itself.
Reminds me of this (fake) interview with Linus where he points out the "easter egg" in git:

"Eventually you’ll discover the Easter egg in Git: all meaningful operations can be expressed in terms of the rebase command. Once you figure that out it all makes sense. I thought the joke would be obvious: rebase, freebase, as in what was Linus smoking? But programmers are an earnest and humorless crowd and the gag was largely lost on them."

http://typicalprogrammer.com/linus-torvalds-goes-off-on-linu...

Um, all I see is:

> Oops! That page can’t be found.

> It looks like nothing was found at this location. Maybe try a search?

Proudly powered by WordPress my ass... It should be embarassed.
> Traditional techniques in git are terrible at documenting conflicts.

What's the reason to document rebase conflicts?

Just the idea that all conflict resolution is fallible and should get a second look. I don't see why a rebase conflict should be treated differently than a merge conflict.
How is this different from git-smart?
I haven't used git-smart, but I read through the docs and it seems that at it's heart it does a rebase -p which won't ever try to see if a merge can succeed where a rebase conflicts.
If your branch conflicts, rebase off master (the branch you're making a pull request to). Then it will merge cleanly. There's no practical downsides to having merge commits in master, but you should never (or rarely) see merge conflict resolution commits. You should be able to rebase to a mergeable state before merge.
If you use a pull request workflow then at the very least, you're forced to merge master into your branch (if there are conflicts) before merging your branch into master.

You should never (not even rarely) resolve merge conflicts on master...

You probably know this but just to be clear, to resolve conflicts on your pull request branch, you may merge master into your branch or rebase that branch on master; GitHub makes sense of either kind of resolution.
The author never elaborates on why exactly he thinks this is needed. I think reading between the lines the reason is that if someone's done a merge/rebase and screwed up a conflict resolution the information about how that's happened is lost forever, so let's come up with some hack to save that information in case there was a conflict.

If that's the case, a solution that would categorically lose less information would be:

1. You're going to push branch you/whatever

2. You rebase you/whatever on on master

3. You solve whatever conflicts you have

4. You make a non-fast-forward merge commit to indicate that you/whatever was rebased as a series with a name

5. You push your conflict resolved & rebased you/whatever branch to master

6. You push the original you/whatever as unrebased/you/whatever

Now you have the original unrebased commits in your repository, you can now simply inspect your history to see what the original commits were, how they conflicted, and how those conflicts were resolved.

Once branches in unrebased/* get old enough you just delete them. In my experience the importance of seeing how someone did something in source control is inversely proportional to how recently it was committed.

In addition to losing less information, your solution allows you to keep merge conflict resolution off of master entirely (if that's your choice).
Indeed, but actually much more importantly it doesn't try to "freeze" derived information that you could just as well construct after the fact from raw information.

This is a very important general concept in Git. It's reason for why it doesn't have an explicit "rename" primitive, instead you construct that information after the fact from the raw history.

Similarly if you're looking to do forensics on merge conflicts it's much better to have the raw original information.

As an aside, the author also seems to be making the dangerous assumption that just because the default merge driver doesn't indicate something as conflicting that he doesn't have to save the original information, his implementation hinges on `rebaseWithoutConflictsPossible()`.

It's possible to have logical conflicts that Git doesn't detect. E.g. if your addition of some code uses a function that's been removed from the upstream.

Thus if you really want to cover all these cases just push your original unrebased branch, then rebase it and push the result (with conflicts, if any, resolved). That gives you all the information you need for after the fact forensics, while keeping your history simple for casual inspection.

i'm pretty sure the simpler answer to this is to always merge, never use a fastfoward, never rebase and to accept history as what it is instead of trying to change it to make it 'more manageable' or whatever.

changing the past to make a single linear thread is just weird imo.

depending on what rebaseWithoutConflictsPossible() is doing it might be helpful though - doing a rebase is an opportunity for the merging algorithms to cause subtle problems, and taking things out of the context in which they were actually made reduces the utility of the history for seeing what was done. the more people you have working on different things at once, the more likely these problems will manifest as something real. if this rebaseWithoutConflictsPossible() check is looking for any potential conflict, not just the ones the algorithms get stuck on then i can see the utility... but its still not necessary if you never rebase and never fast-forward.

"git recursive merge doesn't screwup x% of merges in some linux kernel repo" isn't an argument for it being useful in x% of cases so much as an argument for it causing damage in (100-x)% of cases. the many options available to tweak its behaviour to make it safer should be a giveaway that the merge feature is dangerous out of the box... the difficulty of resolving conflicts and dealing with merges is usually greatly overstated. a lot of programmers seem to have 'mergephobia'... i'm pretty sure we should just suck it up and do our jobs - learn that merges aren't that hard, and spend our time thinking about more important things. :)

Interesting. Basically a commit to remember a conflict when rebasing. Not entirely my cup of tea as I prefer less noise but helpful for some if conflicts generate lost work too often. I find it annoying when see commits on a PR that says "fixing rebase conflicts" etc. "rebase continue" should have inlined those changes to the relevant commit.

My simpler suggestion to avoid unnecessary merges is to try to wrap an alias around merge that simple just prompts whether they tried to rebase first. If you need to merge it often smells like a branch has existed too long.