this post was submitted on 04 Apr 2024
1118 points (98.1% liked)

Programmer Humor

22837 readers
342 users here now

Welcome to Programmer Humor!

This is a place where you can post jokes, memes, humor, etc. related to programming!

For sharing awful code theres also Programming Horror.

Rules

founded 2 years ago
MODERATORS
 
(page 2) 50 comments
sorted by: hot top controversial new old
[–] [email protected] 43 points 1 year ago (4 children)

Please for the love of god don't use merge, especially in a crowded repository. Don't be me and suffer the consequences. I mistakenly mention every person with a commit between the time I created the branch until current master.

[–] [email protected] 5 points 1 year ago (4 children)

Merge is not the issue here, rebase would do the same.

load more comments (4 replies)
[–] [email protected] 20 points 1 year ago (1 children)

That was you! I remember this.

[–] [email protected] 23 points 1 year ago (1 children)
[–] [email protected] 31 points 1 year ago

There's 102 people mentioned in that commit and two of them happen to meet in the comments of a meme thread on Lemmy of all places. I love the Internet.

load more comments (2 replies)
[–] [email protected] 16 points 1 year ago (2 children)

I know this is a meme post, but can someone succinctly explain rebase vs merge?

I am an amateur trying to learn my tool.

[–] [email protected] 23 points 1 year ago (1 children)

Merge keeps the original timeline. Your commits go in along with anything else that happened relative to the branch you based your work off (probably main). This generates a merge commit.

Rebase will replay all the commits that happened while you were doing your work before your commits happen, and then put yours at the HEAD, so that they are the most recent commits. You have to mitigate any conflicts that impact the same files as these commits are replayed, if any conflicts arise. These are resolved the same way any merge conflict is. There is no frivolous merge commit in this scenario.

TlDR; End result, everything that happened to the branch minus your work, happens. Then your stuff happens after. Much tidy and clean.

[–] [email protected] 6 points 1 year ago (4 children)

Thanks for the explanation. It makes sense. To my untrained eyes, it feels like both merge and rebase have their use. I will try to keep that in mind.

[–] [email protected] 6 points 1 year ago (12 children)

Yes. They do. A lot of people will use vacuous terms like "clean history" when arguing for one over the other. In my opinion, most repositories have larger problems than rebase versus merge. Like commit messages.

Also, remember, even if your team/repository prefers merges over rebases for getting changes into the main branch, that doesn't mean you shouldn't be using rebase locally for various things.

load more comments (12 replies)
[–] [email protected] 3 points 1 year ago (1 children)

Yes. My rule of thumb is that generally rebasing is the better approach, in part because if your commit history is relatively clean then it is easier to merge in changes one commit at a time than all at once. However, sometimes so much has changed that replaying your commits puts you in the position of having to solve so many problems that it is more trouble than it is worth, in which case you should feel no qualms about aborting the rebase (git rebase --abort) and using a merge instead.

load more comments (1 replies)
load more comments (2 replies)
[–] [email protected] 18 points 1 year ago (3 children)

Merge gives an accurate view of the history but tends to be "cluttered" with multiple lines and merge commits. Rebase cleans that up and gives you a simple A->B->C view.

Personally I prefer merge because when I'm tracking down a bug and narrow it down to a specific commit, I get to see what change was made in what context. With rebase commits that change is in there, but it's out of context and cluttered up with zillions of other changes from the inherent merges and squashes that are included in that commit, making it harder to see what was changed and why. The same cluttered history is still in there but it's included in the commits instead of existing separately outside the commits.

I honestly can't see the point of a rebased A->B->C history because (a) it's inaccurate and (b) it makes debugging harder. Maybe I'm missing some major benefit? I'm willing to learn.

[–] [email protected] 3 points 1 year ago* (last edited 1 year ago)

I would advocate for using each tool, where it makes sense, to achieve a more intelligible graph. This is what I've been moving towards on my personal projects (am solo). I imagine with any moderately complex group project it becomes very difficult to keep things neat.

In order of expected usage frequency:

  1. Rebase: everything that's not 2 or 3. keep main and feature lines clean.
  2. Merge: ideally, merge should only be used to bring feature branches into main at stable sequence points.
  3. Squash: only use squash to remove history that truly is useless. (creating a bug on a feature branch and then solving it two commits later prior to merge).

History should be viewable from log --all --decorate --oneline --graph; not buried in squash commits.

[–] [email protected] 16 points 1 year ago* (last edited 1 year ago) (1 children)

I feel the opposite, but for similar logic? Merge is the one that is cluttered up with other merges.

With rebase you get A->B->C for the main branch, and D->E->F for the patch branch, and when submitting to main you get a nice A->B->C->D->E->F and you can find your faulty commit in the D->E->F section.

For merge you end up with this nonsense of mixed commits and merge commits like A->D->B->B'->E->F->C->C' where the ones with the apostrophe are merge commits. And worse, in a git lot there is no clear "D E F" so you don't actually know if A, D or B came from the feature branch, you just know a branch was merged at commit B'. You'd have to try to demangle it by looking at authors and dates.

The final code ought to look the same, but now if you're debugging you can't separate the feature patch from the main path code to see which part was at fault. I always rebase because it's equivalent to checking out the latest changes and re-branching so I'm never behind and the patch is always a unique set of commits.

[–] [email protected] 4 points 1 year ago (3 children)

For merge you end up with this nonsense of mixed commits and merge commits like A->D->B->B’->E->F->C->C’ where the ones with the apostrophe are merge commits.

Your notation does not make sense. You're representing a multi-dimensional thing in one dimension. Of course it's a mess if you do that.

Your example is also missing a crucial fact required when reasoning about merges: The merge base.
Typically a branch is "branched off" from some commit M. D's and A's parent would be M (though there could be any amount of commits between A and M). Since A is "on the main branch", you can conclude that D is part of a "patch branch". It's quite clear if you don't omit this fact.

I also don't understand why your example would have multiple merges.

Here's my example of a main branch with a patch branch; in 2D because merges can't properly be represented in one dimension:

M - A - B - C - C'
  \           /
    D - E - F

The final code ought to look the same, but now if you’re debugging you can’t separate the feature patch from the main path code to see which part was at fault.

If you use a feature branch workflow and your main branch is merged into, you typically want to use first-parent bisects. They're much faster too.

load more comments (3 replies)
load more comments (1 replies)
load more comments
view more: ‹ prev next ›