> See the automated rename example. How do you gain the same safety and ease of resolution without git mediate? This is, unlike you say, an incredibly common scenario.
Is it? I'm not sure if I've ever had a conflict that would be resolved by a global find & replace. Globally renaming symbols isn't really all that common. In my experience conflicts are not "usually due to very wide, mechanical changes", they're due to two people modifying the same file at the same time.
> It is true for not only renames, but also whitespace fixes which are infamous for causing conflicts …
Most projects don't go doing whitespace fixes over and over again. In projects that do any sort of project-wide whitespace fixes, that sort of thing is usually done once, at which point the whitespace rules are enforced on new commits. So yes, global whitespace changes can cause commits, but they're rather rare.
> Instead of having to tediously compare the 3 versions to make sure you haven't missed any change when resolving (a very common error!) you now have to follow a simple guideline: Apply the same change to 2 versions.
> This guideline is simple enough to virtually never fuck it up
You know what's even simpler? "Apply the same change to 1 version". Saying "Fix the conflict, and then do extra busy-work on top of it" is not even remotely "simpler". It's literally twice the amount of work.
The only thing git-mediate appears to do is tell you if a project-wide find&replace was sufficient to resolve your conflict (and that's assuming the project-wide find&replace is even safe to do, as I mentioned in my previous comment). If you're not doing project-wide find&replaces, then git-mediate just makes your job harder.
From reading your "process" it appears that all you really need is a good merge tool, because most of what you describe as advantageous is what you'd get anyway when using any sort of reasonable tool (e.g. jumping between conflicts, showing correct diffs, making it easy to copy lines from one diff into another, making it easy to mark the hunk as resolved).
Applying the change to the base doesn't prove that you applied the change to the other version. It only proves that you did the trivial thing of copying one version over the base. That's kinda the whole point of my complaint here, git-mediate is literally just having you do busy-work as a way of saying "I think I've applied this change", and that busy-work has literally no redeeming value because it's simply thrown away by git-mediate. Since git-mediate can't actually tell if you applied the change to the other version correctly, you're getting no real benefit compared to just deleting the conflict markers yourself.
The only scenario in which i can see git-mediate working is if you don't actually resolve conflicts at all but instead just do a project-wide search&replace, but that's only going to handle really trivial conflicts, and even then if you're not actually looking at the conflict you run the risk of having the search & replace not actually do what it's supposed to do (e.g. catching something it shouldn't).
> It's been my experience, especially in the startup scene where business requirements change often, that `git blame` rarely shows you what you want. Files get renamed, moved, re-indented, etc, frequently.
Blame follows renames in most cases (unless you're doing something like creating a new file with the same name as the renamed one in the same commit), and you can use the -w flag to ignore whitespace changes.
> fixing a typo in a line would get you "ownership" of the line (since only the last person to change it is blamed).
That's a UI/UX/usability problem with blame, not an inherent one with the practice. Github's blame UI solves this very elegantly (blame history can be traversed easily), as do some others.
> It's even worse in semi-major refactors due to moved/renamed files being treated as new....
This on the other hand is a real problem with Git, but I don't see that it's strictly related to putting context in commit messages. This issue occurs either way.
In my experience they are correct all of the time for simple renames. It's when you move a file and make substantial edits that it gets confused.
I think it's reasonable to argue that git shouldn't get confused in this scenario, but you could also do your renames in one commit and your changes in another.
The problem with that scenario is that usually it doesn't support a real-world-scenario where you do a rename in the tool (like some IDE) and it doesn't do the corresponding git operation.
(yes, some IDE might have git integration, but personally I don't like my IDE messing with git, except read-only (annotate, diff))
"In this case, the conflicting result is left in the working directory for the user to fix and commit, or to abort the merge with git merge –abort."
I've used git for many years, and I still zip the repo folder, before doing a large merge, since 'fix the commit' can be a large effort with conflicts. Quickly renaming the repo root folder, then unzipping the old version can be quicker/safer, if you are not a git ninja and don't want to loose any work. There is probably proper command for it, but I sometimes get into a git mess that I cannot get out of. (reading stack overflow, trying get reset, git checkout, git reset --hard and so on)
People would get lazy and rename a file without telling Subversion they had done it, so it would write a “old file deleted, new file created from nothing” revision. Most of the merge conflict resolution machinery just couldn’t run without the missing guidance. Git infers someone probably renamed a file you edited or vice versa, which seems risky but works better in practice.
See? That's what I was talking about. Learning the UI before learning what it actually does :)
This only leads to confusion once you use 'git mv' and edit the file significantly enough in the same commit. "Why doesn't git show that it's a rename? I explicitly told it so! Did I do something wrong?"
My biggest gripe about Git, currently, is its poor to non-existent support for renaming files. Basically, it doesn't track file renames at all.
True, in its current architecture it has no way to do it since it doesn't have a daemon or any background process which tracks user actions in real-time, all tracking is ad-hoc, only when git is invoked.
So it basically just side-steps the question, and internally a renamed file is recorded as a file which was deleted and another file which was created, "magically" in the same commit.
When you run merge or log, git tries to guess that a file was actually renamed based on similarity statistics between the text representation. With small, similar files, changed this leads to false conflicts.
I'm not talking theoretically here. I'm talking about something that has caused me, personally, and my organization, many developer hours and real money. I'm talking about something that has hurt productivity and confused me and my users. I'm talking about something that has caused me, just this week, to be alerted to go to work since this happened on a critical project and I'm as the "git expert" was deemed the only one with the know-how of how to deal with those conflicts.
I have spent 2 weeks during covid lockdown, 2 years ago, writing a complicated function which silently identifies those false renames and fixes them before calling git merge. This eliminated many, many support calls. Just last week I have fixed what I hope was the last bug with this function, a nasty corner case.
However this is specific to my situation, where the files are json files that were serialized from the database, and each one of them has a globally unique ID that users can't change. So I'm able to verify which files were renamed in which side and automatically make a "fixup" commit on each side so the 2 sides are as equal as possible (leaving real conflicts in place).
The situation isn't good since this function only works on a single branch merged from the remote. It doesn't work yet between branches. In fact I ought to begin working on changing it to work between branches as I am writing this very comment...
I have many, many other gripes about git, but many of them have been voiced on the comments in this page. But I generally mourn the fact that it is the de-facto source control solution in its current form. Since now its maintainers, quite justifiably, won't break backwards compatibility, and are mostly into fixing bugs and adding some small new features that are QOL improvements.
I still think that some of the bigger pain points could be addressed without breaking backwards compatibility. Similar to what was done with splitting the checkout command to switch and restore, while still keeping the original command.
E.g. for the rename problem above:
1) an optional daemon could be introduced that tracks renames in real-time and records them, both for display purposes in the log, and more importantly to avoid false conflicts during merges / rebases.
2) And/or, users could mark during merges that have conflicts, which files were actually renamed to other ones, in which point in history (perhaps by modifying a generated an input file like rebase does), to help git merge/rebase make more informed decisions instead of relying on statistical similarities.
I dunno, it kind of makes sense. If you do just rename a file it can track it. If you do more than renaming, it immediately becomes ambiguous as to whether you actually renamed the file or just deleted it and made a new very similar file. Or multiple similar files.
I think the real failing is that it isn't very good at handling the "rename and slightly modify" case, even when it theoretically could. Of course it's non-trivial to detect that case, and there are flags you can use to improve the detection but it's still not great in my experience.
It might make sense to allow adding hints to the git commit message to help it. Dunno if anyone has tried implementing that.
While I agree in that Git’s UX is abysmal for the beginner or casual user, no one should have to endure resolving the same conflicts over and over again.
In my opinion, the following configuration should have been the default with Git:
The `enabled` part means: transparently record all resolutions in a database, and re-apply them whenever bumping into the same conflict with the same pair of files in the future.
The `autoUpdate` part means: every time you finish re-applying a recorded resolution, please `git add` the result automatically for me so I don’t have to look for a "conflict" that’s actually no longer there.
> Say you find a typo in a comment, or a small linting error/extra whitespace/etc, and you want to fix it. You know there's no behavioral change. Should be easy right?
There are things like ci.skip option in git for this.
This might not be the forum for it, but I have a question about this - I thought git was supposed to be pretty smart about detecting renames, but in my experience (on Windows) it never does, and I always have to use `git mv`. What's the deal with this?
To be clear from reading some of the other comments, I don't work at GitHub anymore so while I may have partially caused the issues I'm complaining about, I don't have the ability to fix them anymore.
Also, while most GUIs and editors have blame capability (as does GitHub actually), most of them don't ignore whitespace changes (-w), code movement or renames (the -C options) so they're often of limited use.
Finally, I _would_ like people to write good commit messages, I just would like to see a tool that actually uses that work in a way that helps document your code in an easy and valuable way, and the Git/Hub tooling makes that process at best "tedious" as someone in the thread says.
I am working on a new Git client called GitButler[1] and would like to address this at some point down the line, so maybe it ends up being me who helps fix this after all :)
This is completely unnecessary. I've been able to fix every mistake I've seen in the last 5 years with variations of git diff, git branch, git merge, git reset and git rebase and their options, and I've seen some horrific doozies from newbs and pros.
Nice tutorial, but aren't you aware that "git blame -w" ignores whitespace changes? git blame also always follows renames. git's rename detection isn't foolproof (if I edit and rename A.cpp to A-star.cpp at the same time as adding a new A.cpp file it won't detect it), however there are two more blame options for that: -C to follow lines copied between files, and -M to follow lines moved within a file.
Unfortunately, adding -M and -C will quite badly increases the time to compute the blame. Both take an adjustable parameter (min number of characters to match), but I found I actually had to reduce it to catch all the lines in an example of the A.cpp -> A-star.cpp move I did yesterday.
Is it? I'm not sure if I've ever had a conflict that would be resolved by a global find & replace. Globally renaming symbols isn't really all that common. In my experience conflicts are not "usually due to very wide, mechanical changes", they're due to two people modifying the same file at the same time.
> It is true for not only renames, but also whitespace fixes which are infamous for causing conflicts …
Most projects don't go doing whitespace fixes over and over again. In projects that do any sort of project-wide whitespace fixes, that sort of thing is usually done once, at which point the whitespace rules are enforced on new commits. So yes, global whitespace changes can cause commits, but they're rather rare.
> Instead of having to tediously compare the 3 versions to make sure you haven't missed any change when resolving (a very common error!) you now have to follow a simple guideline: Apply the same change to 2 versions.
> This guideline is simple enough to virtually never fuck it up
You know what's even simpler? "Apply the same change to 1 version". Saying "Fix the conflict, and then do extra busy-work on top of it" is not even remotely "simpler". It's literally twice the amount of work.
The only thing git-mediate appears to do is tell you if a project-wide find&replace was sufficient to resolve your conflict (and that's assuming the project-wide find&replace is even safe to do, as I mentioned in my previous comment). If you're not doing project-wide find&replaces, then git-mediate just makes your job harder.
From reading your "process" it appears that all you really need is a good merge tool, because most of what you describe as advantageous is what you'd get anyway when using any sort of reasonable tool (e.g. jumping between conflicts, showing correct diffs, making it easy to copy lines from one diff into another, making it easy to mark the hunk as resolved).
reply