The idea that git is good because it is difficult to use is just "git snobbery", as is the idea that it must be difficult because it's a DVCS.
There's nothing to stop git having two levels of the API, one exposed for tools to build off of with the full complexity and another for every day use.
I don’t think the argument is that the difficulty is a virtue, nobody is trying to be snobby, so try to avoid jumping to that conclusion.
Git just has some inherent complexity. Git does have a steep learning curve that is the root of a UX problem. But it’s not clear what better abstractions there are or how to simplify git. Lots of people have tried to make a higher level porcelain, and the issue isn’t going away. You are welcome to suggest & create a git wrapper that makes it simpler and less dangerous.
Perforce is easier to learn, so you might try using that instead. I use both and I’m becoming more and more frustrated with Perforce because git is so much more flexible and safer and easier to use once you learn how to use git.
For the former you want flexible history, distributed repos and freedom to do whatever you want.
For the latter the history should be sacrosanct and the repository is better be more or less centralized.
git tries to sit on both chairs and therefore has to adapt a quite awkward position.
I also don’t understand your larger point about git and what the problem is. For almost everyone using git, the pushed history is sacrosanct, and the main repo is centralized. The main workflow for rebase is to clean up before making commits public.
"Version control" is a log. I should be able to return to any point in history at any time. I should not be able to destroy this history no matter what I do. The history should be backed up in a remote location.
With git every once in a while these two come into conflict: I'm using my branch as a change management system and then someone else pulls that branch and makes a couple of changes on it. Then I force push and the mess begins.
Regarding centralized repository: say, I have two working copies. In goode olde subversion there was the "master" version in trunk and two local versions, one per working copy. Three versions altogether. Pretty clear which is which.
Now in git I have:
- master in origin repo
- origin/master in wc1
- master in wc1
- actual file in wc1
- all the same in wc2
Seven potentially different versions of the same exact file. That's even without mentioning a stash.
> Then I force push and the mess begins.
That is your problem right there. Force pushing over published history should always be avoided. Don't do that, it is very unfriendly to others you work with. Just always pull, resolve any conflicts, then push your changes without forcing them. If you need to force in order to fix a serious mistake, then notify everyone first and have people hold their changes, then pull everything, resolve the problem, force push, and notify everyone again to "force pull" by first fetching, then reset their branch to what's in the origin verison; using reset --hard will let them avoid having any conflicts after you force pushed. Consider carefully whether the mistake even warrants a force push, or if you can make do with new commits on top that fix the bad ones.
> Regarding centralized repository [...] Seven potentially different versions of the same exact file.
You're conflating multiple different topics. The existence of multiple copies of a file isn't related to which repo is the central one, nor is it some kind of problem.
The origin repo is your central repo. Your downstream repo has to copy from the upstream/central repo if you even want to work on the code. What you called "copies" in origin/master and master are branches, not copies of the file. The only single copy on your machine from your point of view is your local workspace, which expanded from your "master". stash is something that happens behind the scenes to your git database, it's not making more working copies. wc2 is another repo or computer, it's not even relevant. None of these copies you're talking about are visible to a user except the one working copy.
That is my problem right here.
There is no way to tell the difference between "I push to make something public" and "I push to back up my data in some safe location".
That said, making backup data in a safe location isn't what git was really made for. If you really don't want history to be there, you can use cp or rsync, or you can git clone -depth 0 from the backup machine, or just use backup software. There's "bup" which is a backup tool based on git...
And for anyone who doesn't know the primitives, I posted a brief summary on Mastodon the other day:
https://cmpwn.com/@sir/102038690003388821
Also recommend Pro Git's chapter on git internals.
I don't need to know how postgres does paging, indexing, tree diffs, etc to be able to write good SQL.
I don't need to know how typescript compiles to javascript to use typescipt.
I don't need to know how my engine works to drive my car.
I use all of those every day.
But the suggestion here is that as every day users of git should learn git internals to be able to use the tool better.
That's a tooling failure. It's not a failure of the git design or git fundamentals, it's a failure of the git cli.
Things could be better. There's an existence proof. It just lost the mindshare war and so now we're stuck with Git, which I still have to look up basic syntax for because its command set is contradictory and makes no sense. (Is it git <x>? git <y> --x? git <z> <a-b>? Something else entirely? Who knows!)
(I've also had to work with various IBM CVS, and they are universally garbage. When I get frustrated at git, all I have to do is think back to those.)
So yes, Mercurial is better, but is it worth the effort? Not in my experience.
That being said, I use git daily and find that I'm able to do everything I want and more, so I'm not looking to make a switch. Unfortunately, most people don't care to learn how to use git beyond "checkout, commit, push, call for help".
I forget all the reasons why RTC isn't great, but the main one: if the server goes down, you're screwed. This happened several times, and we basically went to the pub instead of working. Slow to check out. Streams sucked compared to branches (especially when the server admin restricted creation of streams, meaning you simply could not branch at all if I'm remembering), and the capability to stash changes/switch branches to work on different work items if one was blocked was also more cumbersome. Code review was terrible.
A centralised paradigm does simplify things a lot mentally, but the workflow suffers IMO.
I guess you can pull a branch or email a patch and diff it with the diff tool of your choice.
There's a few options for gir review UIs, e.g. Gerrit or GitLab. Kind of unix-y, just have the VCS be a good VCS.
> a constructive proof is a method of proof that demonstrates the existence of a mathematical object by creating [...] the object.
> This is in contrast to [an existence proof], which proves the existence of a particular kind of object without providing an example.
Git is good because it is extremely elegantly designed. There are blobs, trees, commits, and refs. When you understand them, you understand pretty much everything about git.
And yes, the interface is a mess.
GIT COMMANDS
We divide Git into high level ("porcelain") commands and low level
("plumbing") commands.I'm not sure if I do, but that's the conclusion the man page + your comment would seem to support.
But once outside that world, the user if faced with the problem that "rebase" is just a special case of "merge" and shared all the complexities and edge cases. And that's hard for fundamental reasons. Git has tools for this too, but their interface shares the complexity of the problem domain.
My last few workplaces were either not git, or relied on git pull w/o rebase. My current workplace has rebase as part of their flow, and I find that, like, 60% of my PRs require force push, which bothers me greatly. Everyone else just shrugs and considers it part of business, but I know what I WANT to do should be nicely aligned and not encounter that problem.
Unfortunately, every explanation I'm like "yes, yes, branching trees, I get it..." and then I'm suddenly in the "...and it says things are different and I don't know why". And because this always happens when I'm trying to get some fix in, I never have the time to study it to figure out what is really happening. It's just "--force and promise myself the next time will be different".
Not really sure what that means as rebase can be used in multiple ways, but you might want to try using:
`--force-with-lease` instead of `--force`
> This option allows one to force push without the risk of unintentionally overwriting someone else’s work
To the degree I understand it, sure:
We have master branch A
I create a feature branch B
Both get updates. Someone will do a rebase of B to the most-recent A and push that. (In my previous workplaces they would have just pulled the most recent A)
Here's where the confusion comes in: If I get the updated B but A has updated again, I cannot pull A nor rebase to A and successfully push the result without forcing. IIRC, on push it complains that my local branch is not up to date, but if I pull it will tell me I am up to date.
At least, that's what I think is the timing - since this involves multiple people I'm uncertain of what exactly occurs and the order, nor why problems are inconsistent. We don't have that many feature branches that have multiple people contributing AND requiring updates from the master branch, but it happens often enough.
The only difference is that one's interactive and the other isn't. If you use `-i` and simply exit out of the editor, the effect is completely the same as not having used `-i`, isn't it? I think moving `rebase -i` to a completely new command could potentially make things more confusing. That new command would be an extension of `rebase` and so could be used interchangeably.
A hypothetical new command would be a simpler version of "rebase" that comes with the restriction described above, that it's not actually changing base.
`rebase -i` doesn't restrict that, does it? There may be people whose workflow includes things like `git rebase -i --onto foo bar baz`. That you don't use it is another matter.
> A hypothetical new command would be a simpler version of "rebase" that comes with the restriction described above, that it's not actually changing base.
You want to remove features from git? Why?
If you didn't mean to say that instead of having `rebase -i` we should only have this hypothetical command, then you can do:
git config --global alias.edit-history 'rebase -i'
Though you may want to add to that to make it impossible to use edit-history to rebase, too. I mean, you did say you wanted the restriction, right?Your right when you say I don't "just" want to introduce an alias because I want to restrict the arguments.
The other issue with that solution is I don't just want a solution for me. I know how this works now, I've already memorized the magic incantation to edit history and later spent the time to understand why the command does what it does (the same goes for basically all the other common git commands). What I want is a solution that works for everyone, out of the box, so we can stop wasting time teaching git internals.
FWIW: the line noise you typed means "Make a list of the changes since three commits ago, let the user edit the list, then apply them". Other than -i step and the length of the list, this is basically a noop -- you're rebasing on an ancestor of HEAD! I mean, yeah, git lets you do that, but I don't know why you expect the syntax for irrelevant nonsense to be simple.
But let's humor you and try to use that syntax for something real. If you typed "my_version_tag~3" it might make sense -- you want to back up to the commit before whatever automation might have added for a release and put your current work on top of the earlier tree as if they had been developed as part of the release. And you have some junk in your current tree you don't want to expose to the customer to whom you are going to hand this test tree, so you want to remove it interactively.
That... sounds like a useful trick. But it's complicated. And the syntax is complicated. So what's a good syntax for the previous paragraph's action?
The "line noise" I typed is an extremely common command that is used to clean up commit history, e.g. squash all your "WIP" commits into a few nice ones. Yes the idea of rebasing onto the same branch is just weird, that's kinda my point, since it's the only way to edit history that git supports (as far as I, or anyone I've ever seen answer a question about how to do this knows).
Also, emacs magit makes this even easier, if you don't mind a more GUI-like interface.
Git doesn't have "reorder patches" feature. Maybe it should. But the fact that its rebase tool can be abused to do this doesn't say anything about the interface value of "git rebase".
Honestly, it seems like the root cause here is that you don't actually do branch rebasing very often, don't see the value of having a rebase tool in the tree, and are just complaining that the trick you do need isn't well supported by the rebase tool you don't use or understand.
My complaint is that git's UI is terrible to teach people, to understand it you have to understand way too many internal details of git.
Yes, making a wrapper for `git rebase -i HEAD~x` (and `git rebase -i <other thing that refers to a commit above head>`) would satisfy this UI nit. It wouldn't satisfy all UI nits, this is just a relevant example.
As for why not submit it myself, I'm sure I'm not the first person to complain about this, drive-by UI changes to a project are the absolute best way to get a ridiculous inconsistent UI. I don't submit it myself because I'm not willing to commit the time to become a core maintainer of git, and without being a core maintainer I don't feel right trying to push UI changes in.
Huh? That is exactly what git rebase -i is. This isn't some kind of "abuse" or "trick", this is precisely what interactive rebase was designed for. What is making you think that rebase is only to be used when merging two different branches?
I generally prefer transparent systems to those that try to figure out what I really want to do.