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).
> 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).
> You can use "git rebase -i" to remove the unwanted commit from the history.
True, but now you're forcing the user to make a bunch of yes/no decisions about what should be kept and what should be discarded. If you make the wrong decision at any point you can lose your work! (I can't remember off the top of my head if Git keeps a tag for the pre-rebase state, but if so that's a lot of clutter that would accumulate over time). And the VCS still hasn't helped you determine what lines of development are independent of each other.
The workflow I am envisioning lets you visually see your working directory as a bunch of independent lines of development. Before you do anything, you can see that your coworker's change is independent of your own changes (because the VCS has analyzed the changes and knows that this is so), which gives you confidence that you can easily remove his change without affecting any of your changes. Then you have the option to simply remove his change, and it's gone.
Doing an update like that would force a merge, but there was nothing to merge. I made no changes. It was a read only (to me) repository. It should have just worked, and would have had someone else on the team not rewritten history.
I'm aware there are more options than delete and clone. My options were to spend time trying to fix my clone to which I had made no changes, or I could delete and reclone from the origin. The pragmatic solution was obvious and got me back to work more quickly than I would have otherwise been able to.
The fact that there are more options to allow fixing a broken clone are nice, but irrelevant. Had git not allowed removing published history, it would not have been an issue.
I'm all for the ability to amend history, which fossil does allow (to an extent). What it doesn't support deletion of old history followed by the creation of new history.
Nah, it's easy. Before every git command, I just tar up the source. When git complains, I can untar to get things working again. To work with others, I fetch a new tree and then use "diff" and "patch" to merge my changes into the new tree.
(seriously, as an experienced professional developer, I actually do this much of the time)
git blame can't possibly work well in all cases, which is why the author is saying that.
Git doesn't store what actually was changed. Git stores how to reconstruct the new file from the old file in a space efficient way.
This is unrelated to storage of who changed what, only "what is the minimal way to reproduce the end state from the beginning state".
As a result, tools like blame take the two versions and try to figure out what someone actually changed, trying to turn applesauce back into apples.
Whether it gets it right or not has an element of luck to it (the diff algorithms are also often based on finding the minimal sequence of edits.). Whether it happens depends on the algorithm and it's heuristics, and often whether there is a single unique minimal sequences that could produce your end state from your beginning state (if not, it's not actually possible to say what you changed with 100% accuracy)
git log -S instead is saying "give me all the times this line seems to have changed", and then you do the work of figuring out which were real and which are artifacts of the diff algorithm.
"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)
This rewrites history, right? What I meant was a feature branch which got merged into master turned out to introduce unwanted behavior, so while a fix is rolled out to the feature branch I'd like to remove that code from master. What I currently do is revert (git revert, which generates a new commit) the merge commit(s) used to bring that feature branch into master, then when the fix on the feature branch is complete I revert the revert I just made and merge the feature branch again.
Sure, I would agree with that, but in this case I already knew what the one commit I was pulling did. And the fetch,diff, merge wouldn't have helped. The file that was destroyed wasn't changed in the commit that was fetched.
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.
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.
Git gives me everything I needed MQ for, but with the complete safety of the reflog. There is no such thing as a change I can't undo. The fact that patch management is "special" in Mercurial is the problem!
With respect to history modification:
First, I rebase a couple dozen times per day. I'm on a team that doesn't use merges unless we have a reason to (this makes it easier to bisect and think about history). I also create, destroy, and rebase many of my own branches every day.
Second, I amend commits a lot. I'll often spike some little piece of code I don't understand, then start amending the commit as I rewrite it with TDD, until the commit no longer contains any traces of the original spiked version. For more complex spikes and TDD rewrites, I'll do it over many commits, rebasing the spike over the rewritten version until the spike commit is empty and gets skipped by the rebase. Doing that in Mercurial would be... arduous. I can easily do multiple history rewrites per minute while doing this.
Third, I amend commit messages a lot, usually with "git rebase -i". Maybe I forgot the ticket number, or maybe the meaning of the commit changed (see the next point).
Fourth, I sometimes do drastic commit rearranging. This is harder to explain, but it usually involves splitting commits (in the simple case) or moving sets of related changes from one commit to another (in the complex case). These are sometimes at the file level, sometimes at the hunk level, and sometimes within a hunk. This is rarer than the others; I probably do it once or twice per week.
Fifth, I "git reset <ref>" a lot. It took me longer to start doing this, but it's useful in a lot of situations. For example, "oops, I accidentally created a merge bubble."
The problem is that this revision will override all the previous ones in the “blame” output so it needs to be explicitly ignored. See a great link elsewhere in the thread on how to deal with that in newer versions of git.
Seconded. The git blame-someone-else tool is just using git rebase and git commit --amend internally to alter one specified commit.
git filter-branch is perfect for this kind of wholesale revision. filter-branch is essential for tasks like: open-sourcing repos that need some kind of cleanup, massaging repos generated by a VCS migration tool, etc. For example, years ago I participated in the move of a large CVS repo to git; there was significant filter-branch post-processing required to create an acceptable baseline)
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).
reply