Don't use Git rebase
137 points by aslakhellesoy 7 years ago | 85 comments- andrewaylett 7 years ago`git rebase --exec {rebuild project}` solves the issue of invisible errors in commits. I'm a big fan of Gerrit's review workflow, which requires every commit to build in isolation. I also usually try to squash my changes into logical independent commits before review.
I like rebase because it's prettier, but I also think there's an issue with the non-rebase case that the OP has missed: unless you rebase, you're setting yourself up for failure in the `git bisect` case: when you step back to find the source of an bug you're tracking down, the worst possible case is that you find it's introduced by a merge and not present in either of the parents. That's much more likely if your merge commits contain fix-ups of their own, which in turn is much more likely if you've got overlapping branches. If you rebase-and-merge then the merge won't have any extra changes, and if you rebase-and-fast-forward then you won't have any merge commits at all.
- aktau 7 years agoYes, yes and yes. We had this issue on the Neovim project a while ago [1]. This caused us to switch workflows [2] (although I would have preferred the --exec approach that you mentioned).
Also see comment [3] by TheCorey mentioning you can use `git bisect --skip`. However, in the mentioned case with Neovim, very few commits actually built, making the process non-deterministic somehow (it kept going in cycles).
[1]: https://github.com/neovim/neovim/issues/6431
- golergka 7 years agoBut that's exactly why I prefer merges - seeing that the problem wasn't in any individual branch, but resulted from the combination of changes in both is the most honest result that I would've wanted to see. Why do you label this as a 'failure'?
- Ballantara 7 years agoIt sounds like rebasing this way ensures branches will not overlap at merge time. This presumably pushes the "combination of changes" into the rebased-before-merging branch, which (if nothing else) makes sure that one committer owns the bug, not two.
- lostmsu 7 years agoIn case of merge that would be merge commit author.
- lostmsu 7 years ago
- andrewaylett 7 years agoBecause it's really difficult to disentangle changes made legitimately in supporting a merge from unintended extra changes that break things.
It also separates changes you made to implement your functionality work relative to the branch point from the extra changes you need to have your functionality work relative to the merge point. With rebase, you get the opportunity to put all the code to implement a feature in one place.
Remember that the usual caveats about writing software apply: you're doing this for the future-you and future-team-mates who come along in a few months trying to make sense of it all. Make life easy for them.
- Ballantara 7 years ago
- fredrikmorken 7 years agoAuthor of the article here. You bring up some interesting points, and I would not be much opposed to the workflow you describe. However, as others mention, if the problem results from a combination of changes, I would expect the merge commit to be the one that contains the error. Moving this errror to a commit that was originally part of a branch without errors is just confusing to me.
- andrewaylett 7 years agoA merge should be just that: merging code without adding extra changes. If you need to make changes, they should be in a separate commit.
But if you had to resolve conflicts in a merge, you might also have had to make changes, and now you've got to work out whether the breakage was because of the combination of features that hadn't been tested together before or because someone changed something while resolving conflicts. Speaking from experience, that's really difficult.
If you rebase instead, the commit that breaks the build contains the code change that breaks the build, and if it's because of a rebase error you've got the opportunity _as you're rebasing_ to detect that.
- andrewaylett 7 years ago
- jbergstroem 7 years agoMy preferred solution is letting "robots" do the actual rebase back to master. In my GH repo I set a label that says 'ready to land' which means that the last CI run will assume that done stuff like proper commit messages and have reworked my commit into how I want them (atomicity, etc). If for whatever reason tests, the extra validations and ultimately trying to rebase to master doesn't pass I get notified as a PR status.
I like the separation between having full freedom in a feature branch without the extra hassle of having to consider timing (active repos usually suffers from this) or typo:ing in commit metadata.
- kstenerud 7 years agoThis would probably be ok for smaller projects. My current codebase takes an hour and a half to build, so a rebase to master will involve anywhere from 10 to 100 rebuilds (1-10 days worth), not to mention the whole process stopping on each merge conflict, which will stretch out the rebase time even more as Murphy's Law will place every conflict outside of working hours.
- joshuamorton 7 years agoWhat are you doing where a build takes that long (and can't be done incrementally)?
- hobo_mark 7 years agoWhen doing anything with FPGAs for example, 90 minutes for a compilation is actually in the low side of things (and incremental builds with EDA tools have essentially never worked for me except in a tiny and unpredictable subset of cases).
- hobo_mark 7 years ago
- joshuamorton 7 years ago
- aktau 7 years ago
- ddevault 7 years agoThere's a more nuanced approach to git rebase. You should use it the other way around - switch to your feature branch and `git rebase master` to update your branch and resolve conflicts. Then test it and `git merge`. I also use git rebase to tidy up the branch's history - generally not entirely squashing it, though.
- gutnor 7 years agoOr well, simply use both. Feature branch, use merge - the feature is an important artefact, and there it is important for the history to show it.
Bug Fix branch, working on a shared branch, use rebase. The branching in those case is a side effect the exact time two colleague committed on the same branch. There is no information you gather from that, it is just a technical blip in the history.
Not quite sure the obsession people have in using only 50% of the tool they have because the other 50% could be misused.
Similarly, digging for a bug in several hundred commits is going to be shit. Hindsight is very deceptive with bug hunting - they always hide in plain sight, if you know where it is, it is easy to imagine "oh, I would have seen it immediately with a merge". Maybe, probably not.
You see that of that kind of overreaction in Management. There is a bug in production, we must introduce more testing, or more testing phase, or change the way we design the around that single experience. But sometimes, bugs just happen.
- keeperofdakeys 7 years agoRebases and merges don't work well together. By default, git rebase will get rid of merge commits. While there is an option to preserve merges (-p), it can lead to some strange behaviour while doing an interactive rebase - see BUGS section in git-rebase man page for more details.
I'd also argue that merge and rebase represent fundamental differences in what commits mean. The former being commits are history, and the latter being commits are features.
- oddlyaromatic 7 years agoI'm a pretty basic got user, just wanted to say this was a really useful distinction for me to read.
- oddlyaromatic 7 years ago
- keeperofdakeys 7 years ago
- jmull 7 years ago> You should use it the other way around
Yes, that's how I thought it was meant to be used.
(At first I got confused reading this article because I assumed that's what they were talking about too.)
- nlawalker 7 years agoNow I'm confused... is that not what the author is doing?
>> the feature branch is reset to master, after which the commits are re-applied on top of feature
Is that not rebasing 'feature' on top of 'master'?
- fredrikmorken 7 years agoAuthor of the article here. Yes, this is what I am describing. Sir_Cmpwn is describing the same workflow as I am.
- fredrikmorken 7 years ago
- nlawalker 7 years ago
- skybrian 7 years agoNeat! You get your choice of linear histories depending on how much detail you want.
But if you use GitHub pull requests and squash your commits, that seems almost the same? The history is there, just not in the repo.
- Sir_Cmpwn 7 years agoI don't like that approach because the upstream history should be authoritative and I don't like to model my workflow around GitHub.
- Sir_Cmpwn 7 years ago
- trumbitta2 7 years agoYep, I use it to keep my feature branch up to date, too.
- gutnor 7 years ago
- fulafel 7 years agoWhat's even the point of using rebase? Merging the development branch into your feature branch periodically is the obvious history preserving thing.
Git already has merge commits, that can be used to label and describe bigger sets of changes in retrospect. There is no need to rewrite the commit history with the benefit of hindsight, it only erases the record of how changes were arrived at, thus losing the opportunity to revisit conclusions from debugging or experiments.
You can also use merge commits to describe sub-units of work in your feature branch. Just rename your branch to some subtask and merge that into your feature branch.
edit: towards the middle of the article, the author also opines "What motivates people to rebase branches? ... I’ve come to the conclusion that it’s about vanity. Rebasing is a purely aesthetic operation. The apparently clean history appeals to us as developers, but it can’t be justified, from a technical nor functional standpoint."
- Vinnl 7 years agoThere's no such thing as "real" history - you don't commit every line of code you add or remove, or even every character. Rather, you choose some points in time to commit.
For me, those are often arbitrary - I can't get something to work at a certain point, so I make a WIP commit with the buggy work at that point, and will come back to it the next day.
Before I merge my branch back into master, though, I want my commit history to be useful. "This is the point where I went home or was disturbed that day" is not useful to future developers. "This is the work I did on this individual feature and everything that's needed to run it and to have the tests succeed is in this commit, and this was the reasoning behind what I did", however, is.
In other words, I rebase to divide my codebase into non-arbitrary units of code, not based on chronology, but on what is useful together.
- he0001 7 years agoWell, assuming that you are adding features in parallel you have an history. You have a branch with feature A and are about to build feature B, which is now based on A, someone else is building feature C which is also based on A. Building B and C might require different or equal changes to A.
There's no guarantee that any of these features will be built in order since they might have different priorities, difficulties or level of acceptance so it's hard to tell which one must or will be done in what order. Rebasing pretty much settles that while merging is much more sane to that workflow. It's harder to keep it functional yes, but it's enabling parallel development. Using rebasing and/or merge isn't a source control problem but a feature management problem.
- Vinnl 7 years agoYeah I think my point was more that a blanket ban on rebasing is too rigorous. I agree that once you want to integrate B and C (or both into A), a merge is usually the best way to do it - and I think that's what TFA was actually referring to.
It fails to consider the case, however, of rewriting B's history internally, not as a way of integrating with A or C, but as a way of making its commits clear. Afterwards, you'd still do a merge of A into B and then merging B back once you see that's successful.
- Vinnl 7 years ago
- yyparm 7 years agoThis makes a lot of sense to me. If you're maintaining a large project having lots of non-cohesive commits make it much harder to figure out what the logical changes were. I care about the set of code changes that were required to add a feature or fix a bug. I don't care about the set of changes that were required to get halfway to working code.
This is also potentially a big deal if you're doing maintenance bugfix releases for a project - that's way easier if porting the bugfix to an older branch just requires cherry-picking a single commit.
- SOLAR_FIELDS 7 years agoThis is precisely why we rebase and squash. We maintain about 4 release branches at any given point and having everything squashed into one or two commits makes a bug fix on master simple and straightforward to downstream.
Although more frequently what we will do is do the bug fix on the furthest downstream branch and because we tag our branches with semver scheme we jus have our prep-for-deploy build automatically walk back up the branches back to master and attempt to merge the feature in along the way.
- SOLAR_FIELDS 7 years ago
- he0001 7 years ago
- pm215 7 years agoThe major usecase I have for rebase is code review. If your code review stage happens at the point of merge/rebase/whatever into master, then rebase allows you to present the feature changes in a digestible way for the reviewers (split up into nice individual commits that make sense individually and are small enough to read and review without too much effort). The classic open source "send patches by email" workflow works this way.
The author is correct that a rebase may require resolving conflicts; but then those conflicts need resolving anyway if you choose to merge instead. It is also possible to miss a "semantic conflict" that doesn't make git complain but produces a commit that doesn't build -- you can put in tooling that checks that each commit builds individually to avoid the "oops, bisect on master isn't much use" issues.
- fulafel 7 years agoOk, if your set of changes is too large to review in one piece, and you put in the work of refactoring your changes into a speedrun-style best possible history so they are cognitively review-friendly, I grant that this is a valid use case for rebase. Though erasing the real history is still a serious drawback, and the unit of code review is still too large. Not many projects work like this, however.
- buserror 7 years agoYou don't have to erase the whole history, just duplicate it.
What we do is to have a developement branch, with the real history. When ready for merge/review, we duplicate that branch, rebase -i (on the same origin) to clean it all up without making any changes -- changes aren't allowed, only history split then merge the clean branch in the dev one (no conflicts: no changes!) and THEN ask for reviews on that clean branch.
If there are further changes, park the 'clean' branch, continue working on dev branch as before, and make any changes needed (typically we use the 'autosquash' naming convention), and re-do the cleanup before re-submitting.
Once the review is complete, just merge again dev<->clean, and merge that in the trunk.
That way you have the whole history complete, and you also have a set of 'public' patches that have been reviewed and potentially can be upstreamed.
- pm215 7 years agoMy definition of "too large to review in one piece" is "more than 200-250 lines", so most non-trivial changes benefit in my view from being split into clean patchsets. It is extra effort that's purely to reduce the code review workload, so it makes most sense when the project is very short of code review resources and the reviewers aren't all the same small set of people as the coders (ie not all working for the same company). Keeping a clean set of commits gets easier with practice though, especially if you do it as you go along rather than trying to do it all at the end. I like stgit for tooling that allows you to think of your branch as a stack of patches and avoid the horrible UI of raw git rebase.
- smackay 7 years agoOn a given feature branch the history is only important if there is more than one review until the work is complete. What the developer does in between these visible/public events is almost always not important. For example in a "make work, make right" situation where the original work is thrown away and rewritten you definitely are not interested in the history.
- buserror 7 years ago
- fulafel 7 years ago
- pandemi 7 years agoThe main use case for rebase for me is to add automatic rebases on pull to the git config.
Normally if you pull from the remote and have local commits not in the remote, you'll have an "extra" merge. Automatic rebase on pull takes care of this, to avoid those useless merges.
- fulafel 7 years agoThey are not useless: they record when git used its fallible automatic merging logic to reconcile changes in two different branches. It works most of the time, but you really want to keep a record of it for later troubleshooting.
Have a look at https://github.com/git/git/blob/master/Documentation/merge-s... to get some idea what is going on behind the scenes in automatic merges.
- derimagia 7 years agogit rebase gives that just fine, even demonstrated here: https://git-scm.com/blog/2010/03/08/rerere.html.
- derimagia 7 years ago
- andybak 7 years agoSurely our tools should simply have an option of hiding useless merges. It's a display problem not a reason to change history.
- mvc 7 years agoThey do. git log --no-merges
- mvc 7 years ago
- fulafel 7 years ago
- sebazzz 7 years agoRebase is often required by open source projects. It makes that a few commits, once integrated, look like they are made directly on top of master instead of merged.
- Walkman 7 years agoPeriodic merges in which nothing interesting is happening are just useless cruft. Just spam the Git history.
- safisher 7 years agoGee, sounds like a fun PR to review.
- Vinnl 7 years ago
- format71 7 years agoI like rebase. Because to me, git is more about communicating changes to other people than finding bugs. Just like testing is as much communicating intent to other developers as preventing new bugs.
So we rebase, and we merge with merge commits. This way, the developer are forced to resolve conflicts one by one on their own branch, instead of sorting out a huge pile in one go on a shared branch.
What I like about git, though, is that you can choose different approaches. Discuss in your team what you find important and use git to support that. If finding bugs with bisect is your main thing, use git in a way that makes that as easy as possible. If your have other needs, you'll have to find other ways of using the tool.
Learning and understanding the tool to use it in the best way to satisfy your needs.
- reledi 7 years agoThis seems like a knee jerk reaction because a co-worker's sloppy rebase caused you to waste a day.
This highlights a bigger issue, many people don't learn their tools well enough.
I've been teaching my fellow senior engineers how to use git the last six months because they've only been using git GUIs until then. They're terrified of merge conflicts and they often make mistakes fixing them.
I'd rather educate people and let them make their own decisions once they can understand and justify the tradeoffs.
- plicense 7 years agoMy thoughts precisely. I mostly use rebase, except when I know multiple commits in my feature branch will cause merge conflict with master - in that case, I save myself the trouble, do a merge and be done with resolving all conflicts in one go.
My ideology is - prefer rebase first, resort to merge if it will let you do the gnarly merge fast. Of course this is because of the development environment I work in where we just don't use bisect and the workflow is different. I also keep in mind that if I work on a different repository with differing testing/development processes this ideology will change.
The first few days I work on any new project(due to a job/project transition), I figure out how I can iterate as fast as I can and see what my time saving points are. How to best use the git I know, on the current repo, is also a minor part of this poking process.
- icek 7 years agoMerge conflicts, history readability, and PR readability are just the things that rebase helps with. I understand, I have coworkers who said "keep things simple; you shouldn't have to be an expert in VCS" as if learning how to use your tools is a bad thing! It's not like Git even takes that long to master.
- plicense 7 years ago
- singron 7 years agoDoesn't squash and rebase eliminate this problem? It removes all those possibly broken intermediate commits once it's in master.
I'll add that another annoying thing about rebasing is that if you make multiple changes to the same piece of code that conflict with changes on master, when you rebase, you have to resolve each change independently instead of only the last snapshot. However, if the changes are in different places, I like the incremental conflict resolution process of rebasing instead of the one-shot merge commit.
- jmiserez 7 years agoYou can have git remember the previous conflict resolutions and automatically apply them the next time you rebase the same code by setting git config --global rerere.enabled true
It’s a builtin feature, see the documentation https://git-scm.com/docs/git-rerere and a description here: https://git-scm.com/blog/2010/03/08/rerere.html
Very handy if you use rebase with multiple commits to the same code.
- jmiserez 7 years ago
- thibran 7 years agoThere is a third option nobody seems to talk about `git merge --squash` (a squashed commit bundles commits into one commit). Which produces like `rebase` a linear commit history, but preserves the single commits.
- imtringued 7 years agoI use git merge --squash so I can commit garbage. The garbage in the feature branch then disappears. It doesn't make sense to preserve those individual commits because they are not intended to work, they may contain code that doesn't even compile, etc. The problem with git commits is that they are immutable and exist forever so you want to get it right on your first try and every commit should be a single "unit" of change that produces a new valid version of your software. Create a feature branch, commit code (often with "WIP" as the commit message) that isn't finished yet and then git merge --squash when it's ready with a proper commit message.
- Pirate-of-SV 7 years agoBy rewriting commits and using `git rebase -i`, `git commit --fixup` you can avoid the garbage and still have smaller commits that passes tests and are easy to review.
- Pirate-of-SV 7 years ago
- rout39574 7 years agoI would think squash a poor default policy; it destroys information in the granularity of commit, and in the commit messages.
- mkobit 7 years agoI agree - you lose the build history, ability to see the incremental changes the author intended, can't go back to the code review to see what happened on that specific commit. I have a very difficult time understanding the desire to use --squash and merge --ff. The problem to me seems like a presentation issue, not a data issue.
- closeparen 7 years agoIf you use rebase or squash merge with something like Phabricator, you can always open up the Diff URL in the commit message and see the granular history (and discussion) if you care to.
- baq 7 years agoNothing is lost if there's no information there in the first place.
- rout39574 7 years agoI agree; if your commits are poorly planned and poorly commented, then I don't see any particular reason to avoid squashing them.
But if your commits are poorly planned and commented, I would recommend trying to improve them, rather than reveling in the fact. ;)
- rout39574 7 years ago
- mkobit 7 years ago
- imtringued 7 years ago
- narsil 7 years agoIn addition to squashing commits, you can merge with `--no-ff` to create s merge commit and semi-linear history showing when new code arrived.
- humanrebar 7 years agoThis should be getting more attention. From the perspective of the master branch, it has the benefits of squashed merges without losing your commit history.
I'll often have a patch that has a few things going on:
1. Refactor code in one file
2. Fix a bug in another module uncovered by the newly refactored code (maybe a code path that hasn't been hit until now)
3. Some quick fixes made while I was looking at that code
...if I made a mistake in step 1, it's likely that step 2, step 3, or both would be useful to keep. If it's squashed and merged, it may be difficult to undo just step 1. And it's good communication to keep each as their own commit because each is its own atomic change.
And I can always squash things myself as I feel the need.
- humanrebar 7 years ago
- pletnes 7 years agoAt least part of the arguments against rebase are arguments for feature branches. Keep master forever and rebase your feature/bug branches, I would rather say. E.g bitbucket has features for this too - prohibit force push on master/release branches, allow on dev branches.
- rsp1984 7 years agoThere are many magnificent tools that can analyse and visualise complex Git history, both GUI- and CLI-based.
Just tell me one. All git tools I know do such a terrible job at this.
- rout39574 7 years agoAny examples of what you find terrible?
Ever tried magit? I don't know if you'd find it terrible, I find it not so bad.
- rout39574 7 years ago
- chrisjshull 7 years agoI'm really surprised no one (article included) has brought up the "Golden Rule of Rebase" (https://www.google.com/search?q=golden+rule+of+rebase), which boils down to "never rebase a shared branch". Git is an extremely powerful tool for collaboration, and it's frustrating when I see that undermined.
- scarlac 7 years agoThe rule makes a lot of sense but most of the articles I found completely ignore if this includes systems like GitHub or Bitbucket. Technically you can create a Pull Request based on the branch yet no-one is actually "using" it. Would you say the rule also applies to such a branch?
- chrisjshull 7 years agoI would. A common thing I like to do is start working on top of work that's in a Pull Request. For example, maybe a coworker is adding an API that I want to use. So long as I'm confident the API won't have drastic changes, and there's just smaller polish or testing to be added, I can branch off of their branch and start working without delay. This also gives me a window to live on top of the changes and give feedback from usage even faster (maybe even before it officially lands).
- chrisjshull 7 years ago
- scarlac 7 years ago
- 2T1Qka0rEiPr 7 years agoI tend to use rebase solely for the purposes of creating tidy commits before I merge my changes into a staging branch.
For example when I'm working on a feature I tend to do n things at once, but I then want to create logical commits which separate the work into logical unit which could be reverted etc. as necessary. If in this process I notice that I've forgotten something (or for that matter, realise later than I've introduced a bug / broken tests) I'll tend to create a patch commit for that logical unit and then `git rebase -i HEAD~n` and then fixup that patch into the original commit.
Also, whenever I'm done for the day instead of stashing I: `git commit -am "wip"; git push; git reset HEAD~1 --soft` (i.e. push my changes up to Origin to avoid any localized mishaps with my PC resulting in a loss of work). I then force push to my feature branch.
I know that both of these "change history", but as long as they're isolated to my own feature branches I see no reason to avoid doing so...
- OJFord 7 years ago> Consider the case where a dependency that is still in use on feature has been removed on master. When featureis being rebased onto master, the first re-applied commit will break your build, but as long as there are no merge conflicts, the rebase process will continue uninterrupted. The error from the first commit will remain present in all subsequent commits, resulting in a chain of broken commits.
Easy, just fixup the commit that (re)introduced the dependency.
> You pretend that the commits were written today, when they were in fact written yesterday,
The author and committer dates will differ accordingly.
- nunez 7 years agoRebase is incredibly useful for me because I commit on every save and squash my commits before submitting for PRs (if working on a team). I commit on every save for three reasons:
1. I can easily undo small mistakes this way,
2. It makes it easy for me to pick up what I've done the last time I worked with that codebase, and
3. It makes it easier for me to tell a comprehensive story when I'm ready to submit my PR.
That said, I do see the authors point about rebasing onto a branch with dependencies.
- jmah 7 years ago"rebase" (like many terms in git) has multiple implications. It sounds like you're advocating for squashing your commits / cleaning up your history, which I don't think anyone argues against. The linked post argues against re-parenting those changes.
- jmah 7 years ago
- shock 7 years ago> Graphs of non-linear history, “train tracks”, can be intimidating. They certainly felt that way to me to begin with, but there’s no reason to be scared of them. There are many magnificent tools that can analyse and visualise complex Git history, both GUI- and CLI-based.
It's a pity the author doesn't mention some of those magnificent tools. Some tools I know/use:
Any others?CLI: tig GUI: gitg, qgit (Linux)
- ajdlinux 7 years agoRegular old gitk is one of the few tools that I find performant-enough to use on the Linux kernel tree.
- xaedes 7 years agoThe only git tool that really stuck with me was "SmartGit". Great log view and rebasing/reordering and squashing of commits with drag and drop. I never have to use anything else^^
- tekacs 7 years agoFor Mac users, there's http://gitup.co/ (I'm not affiliated and it's FOSS).
GitUp is beautiful, incredibly fast and you operate directly on the (well laid-out) graph for almost everything, so you're always acutely aware of the commit history.
(I mostly use Windows + Linux at the moment and this is probably the piece of software I miss the most, even though I prefer shell for absolutely everything else)
- anonred 7 years ago+1 for GitUp. Only annoyance is that it can be slow when staging/unstaging lots of files.
- anonred 7 years ago
- hashhar 7 years agoIf you use VSCode, there's a great extension called GitLens and GitHistory Log. The combination of them makes browsing repository histories, resolving conflicts and tracking changes really easy and fast.
- ajdlinux 7 years ago
- speedupmate 7 years agothis is a narrow view based on someones versioning habits , the point of rebase can also be a solid linear history that allows multiple teams to fork and pull request features between forks. If developer chooses to play merging inside his own repo, fine but as soon as you have large teams working on their own you will end up in merging hell between developers and teams.
say team a does 58 commits per day has 75 team-members and team b has 126 members that are doing 187 commits per day and there's team c, d , e .... n giving non conflicting input to your codebase.
the flow in this case would be to always rebase developer specific features on non-conflicting codebase before you are allowed to pullrequest your changes to central repo. Rebasing to master or to any feature branch developer needs to work will allow them to see any conflicting changes they have made directly in their repo (rebase conflicts and a way to solve those as they know what conflicts, they have introduced the conflicts) instead of merging it together and finding out that the repo they need to PR this stuff will utterly fail cause they are lagged behind or several developers have changed the same files.
in this case rebase flow brings the shit to developer to handle and gives them knowledge that it will break. This mainly happens cause they are not having the latest version of code whereas merge strategy will merge in the conflict and send it to others to discover that thy can't merge any more cause of other developers conflicts.
Merge strategy is not suitable in case where code is edited rapidly daily and some features take , weeks, years, are to be included. Whereas rebase strategy ensures that every developer will always send you changes that are not conflicting with up to date version of whatever is versioned.
- moogly 7 years agoI vehemently disagree. A counter-argument to his `git bisect` problem is whenever I do `git bisect` and I end up on the merge commit being the culprit. At that point I want to cry, because merge commits tend to be ungrokkable — there is so much noise in them.
Also, don't even get me started on `git revert`ing merge commits... Down that road lies sadness and disillusion.
- brianwawok 7 years agoIndeed. Seems like a better solution to his problem is to run unit tests after a merge before pushing it upstream. Then no more non compiling commits.
- brianwawok 7 years ago
- onedognight 7 years agoIf you want every commit to compile then have your CI system check this; no need to blame a useful tool.
- yyparm 7 years agoI tend to think the problem identified by the author is more of a fundamental problem with long-lived development branches that diverge with master - stuff will change under you and it's not always easy to notice.
It's also kind of a problem if underlying parts of the system that you depend on either are churning that much without that being communicated or if they have poorly-defined interfaces and are prone to accidentally breaking things that users depend on.
It's not entirely clear, but there may be some testing gaps too if bugs weren't found.
Maybe merge-based workflow helps a bit but it seems like the pain would still be there regardless.
- fredrikmorken 7 years agoAuthor of the article here. You are absolutely right, and many of the other comments here suggest that people are struggling with problems that stem from the fact that their branches are long-lived.
I would encourage everyone to consider adopting trunk based development (https://trunkbaseddevelopment.com/). I expect this to solve many of the problems people have. Using short-lived feature branches that are merged every day, merges are trivial, and history easy to read. A rebase-based workflow wouldn't be that harmful if you use short-lived branches either, although the argument for preserving history still stands.
- fredrikmorken 7 years ago
- 7 years ago
- jaeckel 7 years agoI liked the style of writing, but the lack of knowledge of the author made me create this account and adding my first hn comment.
Thanks to all others who explained technically what upset me so much.
- blikdak 7 years agoOdd, I would rebase develop onto my feature, resolve conflicts which is easier as I'm dealing with my changes, then merge to eg develop. When time comes for integration I'd probably squash commit changes to the integration branch just to keep that a bit easier to track/undo, but preserve full history in my feature and develop branches do can revert specific commits etc. As always useful comments are a must so I disable automated merge commits.
- TheCoreh 7 years agoWhen using `git bisect` to find a bug, `git bisect good` and `git bisect bad` are not the only options available, there's also `git bisect skip`. You should only mark as bad commits that specifically manifest the bug you're looking for and not, say, build errors or other unrelated bugs. It is true however that the type of build breakage potentially brought in by using git rebase will require you to do more bisect steps.
- ris 7 years ago> It is true however that the type of build breakage potentially brought in by using git rebase will require you to do more bisect steps.
Or leave you with an inconclusive result if the guilty commit also happens to be one of the skipped commits
- ris 7 years ago
- jibberia 7 years agoI use rebase because I often have long-running feature branches (maybe for a couple of weeks) and I want to keep up with changes on master. When I was new to git, I used to merge master into feature branches to achieve the same effect, but my pull requests were littered with commits already made to master.
Is there a better way to keep feature branches updated with changes on master?
- 7 years ago