10 ms·
Merges is the stupidest thing there ever is in the land of source control. Contrary to the author I struggle to find even a single use that would make merge mer
by doombolt 8y ago
Merges is the stupidest thing there ever is in the land of source control. Contrary to the author I struggle to find even a single use that would make merge merited.
My main point is that merges are not easily computable. comm3 = merge(comm1, comm2) is not a kind of function you can run and see for yourself. Instead it is a kind of hand wavy magic in which we declare that those two apples plus a lemon equals three mangoes. You throw the beauty of hash tree out of the window like an overdue christmas tree.
- wodenokoto 8y agoWhat's the alternative? Only work on master and only on one document at a time?
- mkesper 8y agoRebase everything so you get a clean timeline without meaningless "merge of bla" commit messages. Can be made mandatory by turning your repo fast-forward-only.
- domlebo70 8y agoIsn't that just a merge, but done one commit at a time?
- doombolt 8y agoNo it is not, because there is no mystic handwavy commit involved. You just apply a patch basically. Much less this handwavy commit exposed to uninterested parties.
- jamietanna 8y agoGP's comment was that a _rebase_ is a merge, one commit at a time, due to replaying each commit over whatever was there. Although you still fix the conflicts each time, it means you don't have many merge commits as you go along
- wodenokoto 8y agoI'm really bad at rebase, but doesn't rebasing a branch A onto branch B, remove all the history from A?
- IshKebab 8y agoNot necessarily. That only happens if you also squash your branch first. Most people do that though because they don't want potentially unbuildable commits on master. And the value of keeping around WIP commits from a feature branch is questionable.
- de_watcher 8y agoFeature branch has to be a sequence of buildable commits that explain the feature.
- aethr 8y agoRebase has a lot of options, including squashing many commits into one or more "good" commits. This is usually a good thing if you have commits that are "work in progress" commits. You can use squash/skip to avoid having commits in your history that break the project or feature, which is great if you use git bisect. The major downside of rebase is that even if you don't squash/skip it changes the hash of every commit. This is very problematic when others have ever checked out your branch locally, or made commits that haven't been pushed. It takes greater communication between the team in my experience.
- yebyen 8y ago> It takes greater communication between the team in my experience. You can also, as a substitute for greater communication, establish a protocol around branch naming and follow it. What works for us is using the word "release" and "wip" in our branch names. If a branch is a "release" branch, then it is safe to base other work on it. If a branch is a "wip" branch, then it is not safe for merging upstream. These two are not exclusive. For example, you might have a branch "dev" and a branch "release", and maybe another branch "release-dev-wip" – these all have different properties. "release-dev-wip" is a short-lived merge target for features that might not be completed yet. It is not safe to merge this upstream, unless you've checked with all of your colleagues who merged feature branches to it, and they all certified that it is no longer "Work In Progress." The key I think to make this protocol work is to distinguish between "feature branches" and "environment branches" – dev is an environment branch, and a permanent one, so it should not be rebased. Feature branches merge back to environment branches, and environment branches are deployable. You can break this rule, say if someone hotfixes master, which is upstream from dev... but it should probably be an exception to do this, and not a regular occurrence, as many people may have already based their work on "dev" and they will all need to rebase on the new (rebased) dev, in order to get a clean merge later. This is where the communication is not always optional. It might be a better choice, if the hotfix is unavoidable, but the project is large and this type of communication is logistically impossible, to merge in reverse (checkout dev, then merge master – back to dev). It might be ugly, but it's considerate. Either way, there should be a clear protocol and no ambiguity on the matter of whether you have a feature branch or an environment branch when you hold it in your hand. Feature branches represent work, environment branches probably ought to just combine the work, and maybe keep a record of how it was deployed. The branch "dev-wip" is a temporary environment branch – it might be deployed to a dev environment for example, but you should not expect it to remain permanently in the git history. At some point, perhaps it will be renamed to describe the features it contains, and then rebased and merged back to dev. If you merged your feature to it, you might expect that you will need to keep the feature branch around, so you can rebase it on "dev" or "master" later, and finally merge it back. The whole branch might not get merged upstream at once. (You can also call it "release-dev-wip" and then, the person who looks at it will know that it may contain some completed features that for some reason were not ready to merge upstream, but perhaps should not be discarded entirely. I personally like to rebase wip branches on their upstream before discarding them, just to be sure I'm not throwing away someone's work that they may have thought they merged.) Protocol is just a different form of communication that is done up-front. If you decide on a protocol and forget to explain it to your team before you implement it, you will obviously not have solved any problems. It's also important to be clear and confirm understanding, so that you can be sure nobody is imputing meanings that you didn't intend. Some teams might choose to only do prod deploys from the "release" branch, and that anything in the "master" branch must be safe to merge to release and send off to production. You could easily get yourself into trouble if you didn't understand when your team expects to work this way. Some teams might prefer to organize their releases on a "release" branch, and then use Continuous Delivery to trigger prod deploys when the release is merged to master. Other teams might prefer to use a tag for that. Mostly I think we can all agree that you should not rewrite a commit once it has been tagged, but again, this is not something that is strongly enforced by git, so it may vary from team to team. If a release that was tagged broke prod, it might actually make sense to wipe that tag from history and reroute the master branch around it. I've never seen that, but I think you're right, the most important thing is to communicate with your team so there is no ambiguity around these kinds of expectations.
- ShinTakuya 8y agoMake small commits on feature branches and cherry pick onto the master branch regularly. Rebase the feature branches on the master branch regularly. If your commits are small (1 to 50 lines outside of unit test code) at most you'll only have a few lines of merge conflicts. It's always possible to make smaller commits, and it's always possible to cherry pick onto master regularly. If you're not doing so, you're being lazy. This style has more benefits than easier merges. Smaller commits are easier to test and less prone to bugs. Also less likely to be affected by context switching.
- Double_a_92 8y agoIf you got a long-lived branch is extremely cumbersome to rebase that everytime you need something from master, especially if you are not the only developper on it. Maybe our stories are too big, but a feature branch in our company lives at least 3-4 weeks with 4 developers working on it. The only time I use rebase is when I got local commits, and I want to pull changes from my team mates also working on the same branch.
- de_watcher 8y agoMore everyone rebases - less cumbersome it gets. People start structuring their code across time, not just using the commits as dumps.
- ShinTakuya 8y agoYep exactly, also makes the code easier to test, understand, and less susceptible to loss of time due to context switching (since you can read those 20 lines of code you wrote and remember where you were up to in a shorter time).
- ShinTakuya 8y agoIt's okay to have a long lived branch. But you should be cherry picking commits from it to master regularly and rebasing on master even more regularly. It's always possible to do so, and I'm happy to explain how it can be done if you think I'm wrong. If you cherry pick to master regularly, rebases on master are never cumbersome.
- pjc50 8y ago> cherry picking commits from it to master regularly Surely the whole point of a long-lived branch is to contain stuff that's not in master - ie things that are being deliberately kept out of it?
- ShinTakuya 8y agoSure, and that's what you can do. For instance, for a website the long lived branch can contain a commit adding a link to a new feature on the homepage, only cherry picking that aspect at the very end of development so that you can work on the feature in shadow. The point is that you merge anything that is safe to merge, which is usually most of the code if you find a way to hide it or otherwise incrementally change things.
- adtac 8y agoI agree, I too think merges are kinda weird, but maybe it's just you and me having a different mental model. I like small, atomic commits that do just one thing. I frequently rebase onto master whenever I'm working on a feature. When my branch is good to be taken into master, I do a fast-forward merge (basically a commit by commit patch application); no magical merge commit from nowhere. Of course, FF merges are possible only when you're rebased. Things people not used to this workflow might think will be a problem: >Conflicts when I rebase from master Solve them. They're going to happen anyway when you merge into master, so it's easier for everyone if you resolve your conflicts then and there. >Multiple people need to work on the same feature branch Sure, do your work locally. Before pushing, fetch the remote branch and rebase onto it as well. Resolve conflicts and your work history will be pristine. Ask everyone on the team to do the same and nobody will have to resolve somebody else's merge conflicts (because you're the best person to resolve your conflict).
- leowoo91 8y agoWhat do you mean by 'beauty of hash tree'? If you are worried about FF merge, you might be right but no-ff is there as best practice for most of the teams so nothing is lost.
- doombolt 8y agoBeauty of hash tree is that hash(commit) = hash(parent commit) ∘ hash(changes). You could compute that by hand if you wanted. But you can't compute merge by hand since it involves basically rebasing commits to a different tree which is non-trivial and prone to introducing errors. If there is 3-way merge you add some changes on top of that. I don't know what's FF merge, what's no-FF and what you do when your FF merge turns into no-FF.