3 ms·
We never use merge except fast forward merges. So we never have merge conflicts. Of course that means that we might need to rebase and that could hit conflicts
by usr1106 5y ago
We never use merge except fast forward merges. So we never have merge conflicts.
Of course that means that we might need to rebase and that could hit conflicts. With diff3 style rebase conflicts are generally [1] easy to understand. When a commit does not apply cleanly the diff3 style output gives you 3 sections:
1. What the code looks like after the previous commit that has already been rebased to the new branch under work
2. What the code looked like in the original branch
3. What it looked like 1 commit later in the original branch.
Now the question the human is: You (or some one else) changed it from 2 to 3 in the past. Now your code is not 2 but 1. How do you introduce an equivalent change from 1 to something that works like 3?
Once I have learned that principle I could no longer understand why diff3 is not the default or how anyone can survive without it.
[1] Of course there can always be tricky changes. If an automatic diff tool choses unlucky alignments the result is not ideal for humans. But diff3 does not make things worse and generally it does not happen that often.
Edit: A couple of iterations needed. Don't try to type somewhat complex comments on your phone...
- mathstuf 5y ago> We never use merge except fast forward merges. Hmm. I've never really liked this pattern. We never use fast-forward merges for anything other than bringing a release branch forward to track the "current release" state[1] (the old HEAD gets renamed to a stable branch name with the version number in its name). Benefits as far as I'm concerned: - the merge commit can record information about the topic as a whole (e.g., the MR number, `Acked-by` and related reviews, etc.) - it records the merge as a distinct event - reverting a topic is just a single revert command of the merge itself (unless there's some magic to divine what sequence of commits is a "topic" in linear history these days?) - backporting branches is just "branch off of the old release, merge into all relevant branches" instead of individual rebases and tandem merge requests [1] This is possible because we keep "the primary branch can reach all branches" as a property as well. We do this with `-s ours` "syncup" merges whenever a non-primary branch is merged into. This is, of course, all done at once by merging a topic into all target branches, performing syncup merges and pushing with `--atomic` to avoid race conditions.
- usr1106 5y agoPersonally I would probably prefer merge commits, but allowing them only if a fast forward merge were possible, too. So you can see from the history later what commits were merged at the same time (same merge request). Gitlab supports that option, but I have not convinced my team to enable it, so I have no experience. We often have merge requests with more than 1 commit.
- tcoff91 5y agoThis pattern is great. Especially with git log —first-parent. I highly recommend it. We use it to great effect.
- usr1106 5y agoEncouraged by your reply I looked at it again. Unfortunately it is not easy. Our QMS requires us to have related issue number(s) in every commit subject. There seems to be no way how gitlab would get that/those number(s) into the merge request automatically. It would just be a simple script that can extract them from the commits being merged, but I don't see a way to run such hook. So we would need to update our process documentation and our CI to allow merge requests without an issue number. And git log —first-parent would become less useful.
- mathstuf 5y agoThis is solved on our end by having the merge not done by gitlab itself (FWIW, github is bad at making these things too) but instead by our robot. I'm a process wonk, but these checkbox items are still the bane of everyone. It'd be far better if such information were more structured. I'd recommend migrating to git trailers if possible (see `git-interpret-trailers(1)`). While I'm being shameless anyways, features we have in our robot (for merging): - renaming the source branch in the message (MRs from `master` is not uncommon) - treating the target branch as having a different name (so that we can use `refs/heads/release` for "latest release" while future-proofing its merge commit mentions to be `release-X.Y`) - pulling a block of text from the MR description to add to the merge commit - putting `+1` comments, reactions, and other review information in the merge commit as `Acked-by: …`, `Reviewed-by: …`, etc. - merging to multiple branches at once and synchronization (see my prior comment in this thread) The primary deployment tool (there's a library for much of the mechanisms): https://gitlab.kitware.com/utils/ghostflow-director https://gitlab.kitware.com/utils/ghostflow-director
- rkangel 5y agoDoes this not result in potentially having to resolve a conflict several times? If you have 3 commits working in a block of code and then you rebase over master that has one commit changing the same area, do you not end up resolving the conflict for each of your commits?
- mb7733 5y agoOn the other hand, if master has 3 commits changing the area and your branch has 1... It evens out. In any case, I'd prefer to solve several smaller merge/rebase conflicts rather than one large one.
- usr1106 5y agoI think it can happen, especially because I often prefer smaller commits over bigger ones. But if the commit to be rebased was small understanding the conflict and resolving it is usually not hard. For me resolving conflicts has become mostely routine work, not the kind of horror it was when git reported the first conflicts to me in the beginning many years ago. There is also a command git rerere that records how you resolved a conflict and lets you do it repeatedly the same way. A colleague has tried it and said it worked nicely (not sure whether it was exactly the case yiu describe). I suspect he spent many hours on learning it and I am not convinced it has paid off for him yet. I haven't had the feeling that I urgently want more automation. I just run my git diff --ours (and occasionally also --theirs) to make sure I don't make stupid mistakes during rebasing. And in the end of course git diff @{u}.