12 ms·
Avoid Most Rebase Conflicts
- shlokjoshi 7y agoInteresting article
- jrochkind1 7y agoThis seems like a very useful feature, and I don't want any more new git commands/workflows to have to remember.
- twic 7y agoI already know how to use push --force to do that.
- mlthoughts2018 7y ago--force-with-lease is usually safer
- screaminghawk 7y agoAlways safer, and should be the default IMO
- twic 7y agoSituations where you might need to rebase against incoming changes are precisely the situations where --force-with-lease is a no-op.
- mlthoughts2018 7y agoYou are incorrect. This is only the case when the remote copy of the branch you intend to over-write with the force push has already been modified and became out of sync from your local copy of that branch prior to the rebase.
- werpers 7y agoWhat is the problem with the graph in the first figure? Apart from looking a little bit more complicated than one without the merges, will a history like that actually cause any probelms?
- barrkel 7y agoThere aren't any problems. If anything, it's a more honest reflection of history, whereas rebase will erase past current state and remove your ability to wind backwards to the way the world actually was. If you view a neat ahistorical history as a primary artifact of development, then you need rebase.
- dahart 7y agoNothing wrong with the first graph. Avoiding history noise is a minor concern. Perhaps a more practical reason to use control merges without pushing them into the branch is to keep the branch completely stable, allow everyone in the branch to test their own work without being affected by churn in master. Then the integration testing can all happen right before merging back into master. That’s a choice though, it’s equally valid and sometimes desirable to merge from master frequently, and keep the integration testing going, at the expense of some bumps for people in the branch.
- jayd16 7y agoJust leave the damn control merges in the history. It's what happened after all...
- joelthelion 7y agoOr rebase onto the head of Master instead?
- jayd16 7y agoThe whole article is about the problems with that and the pain of working around it.
- bsaul 7y agoActually that's something i don't get (but i'm not a git pro by any means). The article doesn't seem be about the pain to rebase, but rather the pain of regular merging polluting the history. Regularely rebasing the branch on master doesn't pollute anything, keep the branch in sync with master, and makes for a happy final commit.
- jayd16 7y agoWhen you rebase a lot you might have to do the same merge operation multiple times, unless you change the settings like is shown in the article. The trick here saves the merge resolution locally so you can automatically merge again if you have to. I don't think this gets pushed so anyone else (or you but in a different repo) on that branch would also need to repeat the merge operation though. If you save the merge commit, the merge itself is in the history so there's nothing to repeat.
- dahart 7y agoThis is a good point. The author wanted to talk about rerere, and control merges are a great motivator for that. If he rebased the branch, then he wouldn’t be able to write about git rerere. :) That said, rebasing a branch several times before merging back to master is something you can easily do if you’re the only person in the branch. When there are multiple people pushing to the branch, and when the branch changes are large, rebasing becomes impractical and even dangerous. You don’t want to rebase a branch while others are working in it, because it would require a force push. I’d say rebase the branch when you can, which is usually if it’s a private branch and you’re the only person who made changes. Merge into the branch as you go if the branch is large and has multiple people. Commit the merges if you want people in the branch to do integration testing along the way. Use control merges and don’t commit them if you want to keep the branch stable and buffer the people in the branch from changes in master.
- xg15 7y ago> So to relieve some of that tension and ease up the final merge you’re heading towards, you decide to perform a control merge now and then: a merge of master into your own branch, so that without polluting master you can see what conflicts are lurking, and figure out whether they’re hard to fix. It is indeed useful, and just so you won’t have to fix these later, you would be tempted to leave that control merge in the tree once you’re done with it, instead of rolling it back with, say, a git reset --hard ORIG_HEAD and keep your graph pristine. if you use git "linear history" style and will do a rebase at the end anyway, why not do "control rebases" immediately, instead of control merges? At least from my experience, a rebasing on a branch that has substantially diverged can get painful quickly, however doing many small rebases and trying to keep up with master usually works without many problems.
- Groxx 7y agoI've long lived by the "rebase early, rebase often" mantra. Makes this sort of thing mostly a non-issue (tho rerere addresses orthogonal problems, like making the same fixes multiple times in a stack of commits). Besides, you should be coding (and testing) against as close as possible to the final state, as otherwise you discover problematic changes later, and have to re-do more. Personally I slightly prefer merge-y history, as it's more accurate about history... but tooling tends to be a fair bit simpler when it's linear, so I usually stick to linear.
- freetime2 7y agoWouldn’t that require a force push after each rebase, which could potentially cause headaches for team members working in the same branch?
- codyb 7y agoYea I only rebase on branches I’m certain I’m the only one working on. Although having two people working on the same branch can be a pain anyways. At that point I’d probably advocate creating a trunk for the N people to work off. But that of course requires a bit of upkeep as people have to keep it up to date with master.
- 7y ago
- derriz 7y agoOnce I read "this is ugly and pollutes your history graph" as a justification for any git feature, I'm immediately turned off. What really is wrong with having a graph that actually reflects the real history of changes as they were made at the time? Why not keep things simple and improve git-log so that anything you find ugly or that looks like pollution can be hidden while viewing the history of a repo? In this case, for example, would it not be far more ergonomic to add a "--hide-control-merges" flag to git-log? This rerere feature described looks like a lot of the foot-guns git provides. I know I'm in a minority here - I've given up arguing with collegues that it's possible to have a branch&merge work-flow without constant re-basing. Allowing the history graph to be manipulated and changed seems to have become part of the most popular git work-flows even though it's a recipe for serious pain in a distributed VCS. (This isn't a criticism of the article btw - more of the git design/philosophy.)
- michaelgrafl 7y agoI don't see how rebasing often and keeping a linear history is in any way a worse workflow than letting merge bubbles happen. To the contrary, I've changed my preferences from the latter to the former because it turned out to be more readable and to make it easier to find commits that introduced bugs or contain badly done merges.
- derriz 7y agoIf there's more than one person working on the code base, rebasing is only safe if you restrict pushing/pulling in some way. Properly interleaving pushes and rebases is just more mental load and another way to shoot yourself in the foot with git. And I don't see the point just to get prettier git-log output - I've never had an issue finding commits or diffing across more than one commit. But like I said, I've given up arguing about it and have reluctantly embraced my inner rebaser. A small part of me still feels it's a regression.
- einpoklum 7y agoIf your rebasing only rewrites history up to a point that's shared by everyone working on the same branch as you, I don't see what's the big problem. > And I don't see the point just to get prettier git-log output - I've never had an issue finding commits or diffing across more than one commit. You haven't, others (like me) have...
- aaronbrethorst 7y agoI would settle for more clear definitions of “mine” and “theirs.” Bonus points if the definition doesn’t change based on the action I’m performing.
- dahart 7y agoThis was a nice read; git rerere is one of the git features that has been a tad mysterious for me, I thought it was on by default. I’m pretty sure I’ve used it, probably because I read somewhere, just like this article says, that it should be turned on by default. What I didn’t know and wondered while reading is how to clear a rerere, and it looks like you can “git rerere [clear|forget]”. https://git-scm.com/docs/git-rerere https://git-scm.com/docs/git-rerere I have resolved a conflict and then discovered later that I screwed it up, so needed to do it again.
- rurban 7y agoI'm doing that successfully for years. But I added more: https://github.com/perl11/cperl/blob/master/pod/perlcperl.pod https://github.com/perl11/cperl/blob/master/pod/perlcperl.po... The .git/cache is a submodule, so others can easily rebase also. And a lot of helper scripts to rebase and pull --rebase all work branches automatically. All current branches are constantly rebased to master, others default to pull --rebase (aliased to lb), with the shared. git/cache there are no conflicts for years. I'm also doing this for several forks automatically, like adding patches and CI smokes to popular repos like clisp, libffi, openssl, pcre2, coreutils and many more. These are rebased hourly, conflicts appear maybe once a year.