5 ms·
Using Git's rerere feature to escape recurring conflict hell
- 0123456789ABCDE 5mo ago#~/.config/git/config [rerere] enabled = true autoUpdate = true while you're editing git config, consider these: [pull] rebase = true [rebase] autoSquash = true autoStash = true [merge] # zdiff3 adds original text markers and removes matching lines from conflict regions # https://git-scm.com/docs/git-config#Documentation/git-config.txt-mergeconflictStyle conflictStyle = zdiff3 autoStash = true [push] autoSetupRemote = true default = simple [init] defaultBranch = main
- 0123456789ABCDE 5mo agoaddendum these are changes tacked to my git config over time. they're the result of working in a constant crunch state, where smooth forward move was more import than the state of the git history you left behind. these options remove small annoying road bumps. you should avoid some of them if you're working under different constraints, or the commit process differs such that these options don't apply. it all starts with `pull.rebase=true` it makes `git pull --rebase` the default behavior. then comes `rebase.autoStash`, which just wraps the rebase with a stash push/pop envelop. if rebase is not your thing, and you prefer merge, `merge.autoStash=true` works the same. finally `push.autoSetupRemote=true` will skip asking you to set a remote tracking branch, it makes `git push` default to `git push --set-upstream`.
- Izkata 5mo ago[pull] rebase = true Don't use this one unless you really know what you're doing. Multiple co-workers have gotten into really bizarre rebases because of it (like rebasing 70+ commits from master on top of their branch instead of the other way around), it seems to cause more problems than it solves. The man page for "git pull" even has a warning about using this flag.
- 0123456789ABCDE 5mo agotrying to parse your comment, and the story is only getting more convoluted, the more i reread it. "rebasing 70+ commits from master on top of their branch" is not a real thing like, i want to believe you. it just doesn't work the way you're describing it.
- Izkata 5mo agoI didn't catch the exact commands they were doing, but their branch was made that far back, that's how it was that many commits. Support was putting that setting in ~/.gitconfig for all new laptops, and we didn't know it was there. I saw one of them going through this huge rebase and was suspicious about how a pull was causing a rebase at all since this wasn't the default (and this particular co-worker wasn't the kind to explore these settings), so we went looking for it. After removing the setting, the command they were running worked exactly as expected without any surprises. They'd also said they thought they were using git wrong somehow because that wasn't the first time it happened.
- 0123456789ABCDE 5mo agoso, your colleagues merge features into `master` locally? no pull-requests, no branch protections for `master`. i mean this works, but you probably need those rails in place.
- Izkata 5mo agoNo, master is protected. I think they were trying to update their local master so they could resolve a merge conflict.
- beart 5mo agoI believe push default simple is the default in git now and does not need to be explicitly set.
- 0123456789ABCDE 5mo ago> This mode is the default since Git 2.0, and is the safest option suited for beginners. the docs checkout, ty
- cautiouscat 5mo agoEvery time I think I am adept in git, something like this is shown to me. I really should read into it more lol.
- davidelettieri 5mo agoI'm using these options https://blog.gitbutler.com/how-git-core-devs-configure-git https://blog.gitbutler.com/how-git-core-devs-configure-git and I'm happy with it
- dools 5mo agoI never get conflicts during a merge because I only ever merge in one direction. I get all my conflicts on branches because I rebase before merging. I started doing this years and years ago because I kept coming across these mysterious silent regressions with my team. I searched something like "git merge silent regressions" and came across this stackoverflow answer: https://stackoverflow.com/a/28510260 https://stackoverflow.com/a/28510260 That completely fixed the problem. Now I only ever get conflicts on my feature branches. The rule is always: rebase away from main, and merge towards main. All conflicts are then on your branches, never on main, and always from rebase, never from merge. Then I set the pull behaviour to rebase, too. I've never had a silent regression since, and never had a problematic conflict scenario. I did recently learn about ORIG_HEAD though which was very cool, because I had accidentally rebased to main instead of to a dev branch from which I had created a bunch of worktrees, then when I merged back to the dev branch all hell broke loose, and I learned that I could revert a merge by checking out ORIG_HEAD: https://icinga.com/blog/undo-git-reset-hard/ https://icinga.com/blog/undo-git-reset-hard/
- ubercore 5mo agoI've never even seen someone suggest a rebase master onto feature workflow! TIL.
- dools 5mo agoI think the terminology would be the other way around, like you're rebasing the feature onto the main: git checkout feature git rebase main git checkout main git merge feature that way you get all your conflicts on the feature branch during rebase and your merge is always clean.
- barbazoo 5mo ago> I get all my conflicts on branches because I rebase before merging Pretty sure it's the other way around. You're on the branch and rebase it atop current master. If you merge after that, you won't have merge conflicts.
- barbazoo 5mo ago
- adithyassekhar 5mo agoDo people really merge left and right between branches? Tell me if I got this wrong, this is how I work. You got 4 devs. Each branched off from master. And we never merge from each other. Suppose 3 other people merged to master I pull it from master and fix only those conflicts. I’m not bringing your code into my branch unless it’s already finished and on master. If I need something you’re working on and it’s not on master when I need it, it’s a much larger planning issue. If you have multiple environments before a stable master, do it only in one direction: feature > dev > staging > master. Don’t merge branches straight into staging or master. I thought this was how everyone worked.
- powersjcb 5mo agoYeah, I absolutely never run into this problem. Sometimes we will have a huge stack of changes one of us is "finished but not clear to merge". either: - We just swap ownership of the branches and eng 2 now commits directly in branch 1. We review the final content together and typically pull in a 3rd person to review our combined work. Eng 1 either pairs with eng 2 until its finished or starts on a task that is decoupled from those changes. - We use an integration branch that gets threated like the temporary master branch until the feature is ready to merge.
- convolvatron 5mo agowhen you're not just doing small patches (like Greenfield work), and you have multiple developers, it can be unreasonable and wasteful to do what you describe. say we're redoing the way memory management it being done, or changing a foundational api. A and B could go through master, but they'd have to redo a whole bunch of work. Or we could make an integration branch where A and B hash things out together and only push to master when their work is done. you can also see how this allows a lot more back and forth about the places where the designs interact rather than 'I got in master before you, so you get to eat a multi-day merge and I'm outta here' this kind of interaction shows up more in a 'release' based model than CI environment, and one where the cost of testing is non-zero (because we're actually doing testing). I know that's not a very popular model, but not all software development is CI websites.
- 5mo ago
- mamcx 5mo agoI use rerere when "forced" by team to use rebase. It not even work that much at the end (you can't control workflows outside yourself, that is why git ux is wrong: it desperately need total discipline). THEN, I move to jujutsu. Only has a few problems at start trying to use it as git, but after get the idea, all fine. BTW, this was with the same team and they never know, so JJ is in fact better: It survive OTHERS workflows.
- nchmy 5mo agoNo idea why this was downvoted. This is one of many ways in which jj is far better than raw dogging git
- cub-creature 5mo ago[dead]
- kazinator 5mo agoYou should not be seeing the same conflicts over and over again in a situation in which you are on a single branch, just rebasing your unpublished commits. You might get conflicts regularly, if people are touching the same area of the code that you are touching, but not the same ones. rerere mainly comes into play when people have to backport commits into multiple similar branches, due to having a heavily forked git landscape.
- saghm 5mo agoAgreed; making conflict resolution separate for each commit rather than requiring a stateful flow where interruptions need to abort the entire process is one of the many killer features of jj.
- swift-lambda 5mo ago[flagged]
- barchar 5mo agoYou can use the rerere-train script in the git repo to populate rerere from existing merges. I use this when something in a merge has regressed a big feature branch and I need to bisect. I can train rerere then rebase on the 2nd to latest merge-base, all while still doing no extra work if there isn't a regression.
- jstimpfle 5mo agoRebasing all the time will most likely result in intermediate commits that don't build anymore (because who builds all the intermediate commits after a rebase), and which don't make sense anymore as a "history" of changes. So my simple resolution has become: don't rebase anything beyond trivial. I use rebase -i to merge, delete, or reorder individual commits on an insolated feature branch. Anything else? Not worth the effort in my opinion. Just merge, in any direction. I even merge between feature branches sometimes, though one must be aware that this essentially glues the two feature branches, meaning either both or none can get merged to master. Something worth stressing: The most important commit is always the one HEAD points to. Older commits don't matter so much to the degree that cleaning them up later is wasted time. The most value of git commit graph comes as a support structure for git merge. In most cases, nobody gives a shit that all intermediate commits are perfect for some definition of "perfect". Most commits will never be read again.