Like anything else in software development, the hard part to learn is the abstractions, not the syntax. People struggle with git because it's an immensely powerful tool. "git reset" has quite simple syntax, but it confuses the hell out of even experienced git users because it's very clever and potentially very dangerous.
Of the altered syntax in Legit, "switch", "sync" and "publish" make sense, but "harvest", "sprout" and "graft" are no more intuitively obvious than the git equivalents.
I found that the syntax _was_ the hard part of git. That and the often-terrible man pages. Both docs and syntax are inconsistent, verging on random, and full of irrelevant details. It's pretty hard to figure out the actual concepts beneath all the noise and misdirection.
the git vs EasyGit diff basically summarizes what I'd change about git.
I'd be curious to see a few examples. Git is guilty of using a bunch of non-standard nomenclature, and of using existing terms in non-standard ways ("checkout", I'm looking at you). But I certainly wouldn't call the interface or syntax "inconsistent" or "random". It's actually very tersely designed and very well put together. The "actual concepts" are, for the most part, first class citizens in the interface.
> But I certainly wouldn't call the interface or syntax "inconsistent" or "random".
Uhm, NO WAY.
git checkout works on both branches and files.
I can `checkout remote-name/branch` but I have to `push remote-name branch`. Deleting a local branch is `branch -D` but deleting a remote branch is (I still can't fucking believe it) `push remote :branch`. It's surprisingly hard to unstage a file.
If a rebase fails, it gives you exactly one warning and then forever complains about a dirty index tree. The error messages are borderline incomprehensible for someone who doesn't understand git internals (refs/head say what?). The reset command is far to easy to typo into oblivion.
What else. I haven't spent a lot of time thinking about it, but obtaining an exact list of differences between branches is hard (git `log sha1..sha1` compared with `git log sha1...sha1`).
This is just off the top of my head. Git is great, it's fast, I don't understand people who are still on svn, but the user interface is abysmal.
Git checkout is actually pretty consistent and only really works on branches. When you say it works on files, you actually mean it has a shorthand that works on files:
git checkout my-file
... is actually using a lot of smart defaults. Namely, you're actually running ...
git checkout HEAD -- my-file
If you don't specify a branch or identifier, git uses HEAD by default in most cases. (When you run git diff other-branch, you're actually running git diff HEAD other-branch.) And the dash-dash syntax is mostly optional in modern git.
Not inconsistent at all, as far as I can tell. In fact, most features of git that I use on a regular basis are completely consistent and orthogonal. The exceptions are submodules and remote cache branches...
wc is "word count" it's not a sane default. it's a obviously explicitly behavior. if git checkout were called 'git checkbranch' then you would have a point.
tar does not have sane defaults. it requires explicit flags. your example (besides not working because as i said, it does not have defaults) could very well be `tar -c files you want to copy -f destination.tar` and all would be well. you actually still repeat the very first tar command line example you ever saw to this day, even not agreeing with it :)
> I can `checkout remote-name/branch` but I have to
> `push remote-name branch`
So I can use the same command in svn/cvs to switch branches and publish changes?
> Deleting a local branch is `branch -D` but deleting a
> remote branch is (I still can't fucking believe it)
> `push remote :branch`.
It's not that hard to understand. Most git commands only affect the local repo, but git-push and git-remote are used to affect the remote repo. It makes sense not to break that convention because some people feel it should be organized differently.
In any case, writing to remote repos was never part of the core design of git. It was designed to be a distributed group of people that would pull down remote branches, make changes, and then submit pull requests to the code maintainer (or use the various 'email patch' commands). Remember that it was developed with Linux kernel development in mind, where there is a hierarchy of developers responsible for sections of the codebase.
>So I can use the same command in svn/cvs to switch branches and publish changes?
No, it's about the notation for remotes and branches. It's confusing that sometimes when I refer to a branch I call it remote/branch and other times I call it remote branch. It would've been way more consistent if it were always remote/branch.
As a result, git push sometimes gets confusing. Suppose I'm on staging. I then say, git push heroku staging:master (push the staging branch to the master branch on heroku) whereas git push staging:heroku/master is imho easier to understand.
By default, git will only pull branches out of refs/heads/* on the remote repo. You can configure it to do otherwise though. This allows you to store branches on the repo that not everyone will necessarily pull down into their repo. This is obviously less useful with a smaller group of developers and/or a private repository.
> Is there a reason for the syntax in checkout
> being remote/branchname then? I care about
> consistency more than the specific syntax.
In git-checkout, you're resolving the branch name locally. When you sync to a remote, a copy of all branches from refs/heads on the remote repo are pulled down and stored in refs/remotes/$remote_name/branch_name. So, refs/heads/master on the remote repo is refs/remotes/origin/master locally.
The right side of the ':' in the git-push command resolves on the remote repo, but git-checkout resolves in your local repo.
Also look at the git-rev-parse manpage for info on the resolve order/etc for branch name shortcuts. It's the 3rd bullet point under 'Specifying Revisions.'
OK, I'm seeing where you're coming from. But I guess I don't see the severity. Yes, git's terminology is highly non-orthogonal (the umpteen different synonyms for the "index" was pretty amusing). But... that's just the frosting. Who cares how messy it is if the cake is still good?
Yes, it's messy. But I don't really see that it hurts comprehension. And it hurts learning only inasmuch as you can't guess at a command and have to check the man page (i.e. I know there's a diff variant that checks the index vs. HEAD, what's it called?). I can't honestly say I found it difficult to understand what the index was due to this.
You can recover from a git reset --hard with the reflog as well, though of course if you had untracked changes you'll lose those. (I usually use git reset --hard in the process of renaming branches and not to get rid of untracked changes, so this isn't a problem for my workflow.)
While I'm perfectly happy with the stock git porcelein commands (and generally don't like any attempts at simplifying them, including gui tools) other developers having a different workflow isn't the reason.
I think having shortcuts and wrappers like the above is fine if you have a good understanding of the underlying data structure you're manipulating. You're only going to run into problems if you treat these commands as magic and just hope they work.
Switch, synch, publish, unpublish - those all made sense, but when they started adding things like 'sprout' and 'graft' it just passed into the realm of trying to be too cute with the branching metaphor for my tastes.
Personally, I'd pick git-flow over this. It seems more useful and makes, syntactically, more sense (though it can get a bit verbose at times `git flow feature start some-feature`). Starting and finishing features, hotfixes, releases, etc. handles all of the necessary branching, merging, and checkouts for you while adding structure and basically documenting the lifecycle of the code in your commit logs.
Maybe it's not as 'human friendly' as sprouting a branch, but starting and then finishing a feature sounds pretty straightforward.
I welcome all attempts to create a better UI for git. Perhaps legit isn't it. Don't care. Eventually we will get this right.
I prefer git's internal branching model and few other features to mercurial but I really prefer the UI to git.
Keep it up people, eventually we will have a better ui.
All that said, I'd encourage people who are doing it, to not add the 'git' namespace. Create your own and just use the internals. Systems that add new 'git *' commands are just confusing an already confused situation.
I don't disagree with the purpose, the git CLI interface is pretty inaccessible to non-developers—more than it needs to be.
But you're totally right about the implementation. This just adds more commands under the git namespace, muddying the waters as much as providing a simple interface.
If the goal is to make git for mere mortals then what is necessary is to create new porcelain from the ground up and call it something other than git. That's a lot more work obviously, but git internals were defined to enable just that! Then in the fine print you could say "oh btw there's git under there for anyone that needs it". That's my idea, but maybe it would be better to just use Mercurial?
In more general terms, the 'porcelain' is the user-friendly interface commands, and the 'plumbing' is the internal commands.
With Git, it's often said that some of the 'porcelain' commands only make sense in the context of the 'plumbing' ones, and you should understand the internals first before being able to use the more user-friendly interface. It's things like this that lead people to create more friendly interfaces like Legit here.
The same argument could be used with assembly language vs. Ruby/Python, but that doesn't stop people from using higher-level abstractions to get things done easily. They exist to streamline a process.
I see much ado about nothing in these comments. Is it really that awful to alias away an odd set of tools that sometimes contradict one another? That's what every high-level language does. That's what every decent UI does across any paradigm.
Abstractions make things easier for the human in many cases. If Legit increases the productivity of a team of developers and gets newbies using the Git VCS, more power to them and its use. They can learn the internals later.
> you join a project that uses assembly language, which you find too hard to learn, so you decide you'll be using Ruby instead.
That's not my point. My point is that if legit gets people into using Git as their VCS, it seems silly to attack the idea because it isn't the current norm of engineering. Lessening barrier of entry to using a powerful VCS is not bad in and of itself. Not everyone jumps into assembly language. Plenty jump into higher-level languages and find themselves deeper in the rabbit hole as time progresses.
To a newbie, this legit script appears far more accessible than git's stock interface. Is it bad that GUIs exist because the command-line is often more powerful to an experienced user? Why is it so bad that this tool exists and can be used to increase overall engagement and entry into the world of Git?
The idea of a clean abstraction is you can predict what a particular operation will do without knowing its internal implementation.
For higher-level languages, this is generally true for the effect of a command: you can work out what a line of Ruby does without needing to think about the underlying assembly language. There are other abstractions (aka levels/layers), such as virtual memory, the OS and the implementation of the CPU itself in terms of architecture, transistors, silicon doping. (Sometimes these abstractions are said to still be "leaky" because to understand performance issues often requires knowing the underlying implementation - that's important but distinct from just knowing what it will do.)
A common criticism of git is that the abstraction is not clean - you need to know what it actually does underneath in order to predict that a command will do. It's not just a problem of an inconsistent UI (though it is that), but that the user model that the command sets out (the abstraction) does not match up with what git will actually do.
The OP's criticism is that legit (great name BTW) doesn't address this: people will use this simpler, friendlier UI, and inexplicable and weird dangerous things will happen (e.g. data loss). C++ might blow your leg off, but git can make you never have existed.
NB: I haven't looked at legit closely enough to tell if this criticism is valid (and OP offers no support - OP, please elaborate). I'm just clarifying the issue.
-1, as a git user who finally submitted to learning the internals, I think this is not the right way to design software. I realize linux/et al are all geek inspired technology festivals, but to imply that a good User Interface and human accessible commands are unnecessary is... silly, the rhetoric reminds me of the elitist GNU/linux propeller heads back in 1999 who would constantly and derisively snort in disdain at "Windoze" users because they didn't know how to do a find / -name myfile.txt -print. Especially the one's who argued vehemently that the '-print' option made any sense whatsoever.
I have always seen git as a kind of assembler language for version control. We are now starting to see some second generation languages built on git. The first batch may not be perfect, but over time we will see improvements.
I welcome these attempts to abstract git and make it more accessible. I haven't yet seen one that I think I would prefer over native git, but am looking forward to see what develops.
Underneath, git is actually based on a really simple tree-of-objects data structure. All those esoteric features are built on an elegant base; understand that base, and you can understand anything git does (though it may not be obvious at first).
I don't want to venture too far off-topic, but when the Perl 6 folks re-designed regexes, they found out that they weren't really designed for anything; the syntax just grew, and common features were sometimes longer than rare ones: http://www.perl6.org/archive/doc/design/apo/A05.html (section "Poor Huffman Coding").
I haven't studied enough of the Git plumbing to know what's going on underneath, but I suspect that the same thing is going on, where features are added without regard to other ones already present (feel free to correct me on this)
I understand that Git is a fairly complex utility. But you can accomplish a lot just memorizing about 5 Git commands and what they do. Besides, if you decide to use an abstraction such as this one without understanding the plumbing, what do you do when 'git sync' fails due to conflicts?
The same thing I do when my hardware misbehaves and I don't understand how it works and why it failed.
Just kidding. Argument by Reuction Ad Absudum is fun, but in this case, you make a good point. There is a difference between a utility designed to make someting you understand easy and a utility designed to put an easy-to-understand facade in front of something you don't understand.
git's user interface is terrible and very counter-intuitive, but if you want to work in a team or, more to the point, be productive and leverage what git has to offer, do take the time to learn its native user interface.
That's silly. As developers we constantly try to make better interfaces for our users. When it comes to our own tools we supposed to put up with difficult interfaces because that's the way it is?
Engineers seem to treat mastering the command line and complex tools as a badge of honour, and as a way of differentiating themselves from the noobs. If there is really an easier way then is that really a bad thing?
> That's silly. As developers we constantly try to make better interfaces for our users. When it comes to our own tools we supposed to put up with difficult interfaces because that's the way it is?
We're not talking about a different interface here but a new terminology.
It's a bit like saying that you think English is too hard so you'll be communicating in Spanish from now on. This is not a realistic decision in a world where you need to work with a lot of people who all communicate in English.
Extending your vocabulary is nothing like learning a new language. A text based interface is improved by choosing words and symbols that better represent a command with relative brevity and simplicity.
The concensus seems to be that commonly used complex actions in git have a less than intuitive structure and syntax. I think it would probably benefit from the introduction of new terminology.
Your analogy is wrong "terminology" and "language" encompass a radically different scope.
The actual analogy you should have used is: English is too hard, so we will use simplified, task specific terminology (or better yet, pictographs) to ensure task specific communication in a multilingual environment.
When you are working in a multi lingual environment that has built in restrictions and a short list of common terminology (like at an assembly plant, or github commands) it is much easier/faster/simpler for a korean and brazilian (lets just say) to communicate using a short list of common, simplified, task specific english terms like "bathroom, please", "dangerous", "stop production", "broken", "connect here", "lift here", "this side up", that is oriented around the things they actually do at their job.
Hell, give this thing a GUI that is just a bunch of easy to recognize icons and you will have something approaching the real world solutions that are commonly recognized as best/safest practice.
I think the only two commands from this I like are `git sprout newbranch` and `git unpublish branch`. But only because I think `git checkout -b newbranch` and `git push origin :branch` are stupid syntaxes for doing what they do.
> git push origin master:refs/heads/experimental
Create the branch experimental in the origin repository by copying the current master branch. This form is only needed to create a new branch or tag in the remote repository when the local name and the remote name are different; otherwise, the ref name on its own will work.
So, a direct substitution of `git push origin :experimental` says
Create the branch :experimental in the origin repository by copying no branch
I definitely think that could use another layer of abstraction.
It seems like the use case he's optimizing for here is if you're accidentally on the wrong branch, and need to move your working changes over to the correct branch.
Personally, I almost always use stash if I'm not quite ready to commit, but need to quickly fix a bug that takes precedence over whatever I'm currently working on. I stash what I'm doing, fix it, and them come back. Some of these operations seem at odds with my workflow.
I've used that workflow too. What disturbs me about the `git switch` proposed here is the unstashing. I think the intended optimization is more general: when you're trying to switch to another branch for any reason but git doesn't let you because of unsaved changes. But your use case of being on the wrong branch seems like the actual optimization for a fairly (at least for me) uncommon workflow. More frequently I, like you, stash and switch, then possibly do something (or not) like immediate bug-fixing, then switch back and unstash only then.
I'm in full agreement with the other comments I'm seeing. These kind of additional tack-ons are somewhat pernicious to actual team-based version control, because it promotes abstracting more of the core functionality of Git outside of the user's control. This causes breakdowns in mutual understanding and the ability to communicate at the worst possible time -- when people are trying to figure out why there are weird changes to production code, or what happened to the changes they made. As a technical lead, I would actually tell a developer using this to cut it out and learn the real commands so they know what they're doing.
I wrote something vaguely similar a while back, I imagined it would be useful in a hackathon context for people who had never used git before. The biggest problem was that it doesn't help people understand git, whereas all of the regular git commands fundamentally make sense if you think about the way it's implemented, and also lead you toward and understanding of git.
My version was called jerk--it is a little meaner than git, and supports operations like "undo".
If you know what these commands are doing under the covers, these commands are a true time saver. If you don't know what these commands are doing, they're basically "magic" and in the hands of inexperienced developers could be harmful to their education on Git.
Actually, a 'debug' or 'dry-run' mode that simply prints out the git commands without running them would be useful for all kinds of users. Newbies can learn from it and pros can make sure that the commands are going to do what they expect it to. With git, I know what each command does but my concern with legit (and similar) is that the higher level commands might not do exactly what I think based on their name/description.
I really like this idea. I consult Stack Overflow or the git man pages frequently enough to make it annoying, but infrequently enough to have the appropriate magic incantations become instinct.
However, if I am going to distance myself from the bare metal of git, why not go all the way and use something like GitHub for Mac? That seems like a true "Git for humans". I love working from the command line as much as possible though, so I will watch this closely to see if it becomes widely adopted.
I like the idea here, but see one significant problem that will prevent me from using these aliases. The git publish alias doesn't take a branch name, so if you have multiple remotes for the repository it will just publish to one of them. Which one? Well, the code in legit/scm.py reads
It's probably better to just write one's own wrapper for git that best fits you/your company's workflow, especially if it's for your company, since you can better justify the time spent writing the wrapper code. As a point of reference, the company I work at (five devs total) is moving off cvs(!!!) to git, but writing a wrapper tool to git to create branches and set them up in the manner we need for our product.
The point is, the best way to improve suboptimal behavior in an open source project is to engage with the project and advocate changing the behavior. If there is truly a defect, or a behavior that so needlessly violates the principle of least surprise, then fix it at the project level.
Incremental and clarifying progress is always beneficial.
I am on the fence as to whether this is clarifying or not. Git's problem is not just that the command structure is... esoteric, it's that once you're off the golden path, finding your way back onto the path is extraordinarily difficult.
I am unclear as to what extent legit mitigates the second (thornier) problem.
>Exactly! And that lingua franca already exists. This is only useful if you would like a new syntax for personal use and you're too lazy to or don't want to use 'git alias'.
Well, the lingua franca that "already exists" is the standard git syntax.
This syntax pains some people. Now, to alleviate the pain they could either use each their own aliases OR they could share a common new "lingua franca" of aliases.
That's what this project does.
In other words, what you're saying is:
1) a lingua franca is important
2) so use standard git, which is a lingua franca, or have your own personal aliases.
This just doesn't follow.
If a lingua franca is important, then, FOR THE SUBSET OF PEOPLE THAT DON'T LIKE GIT SYNTAX, to have a common alias lingua franca is also important.
It doesn't matter that it's less of a "lingua franca" that standard git-alese, because it is still a lingua franca for that subset, and solves the problem they have with the more established lingua franca.
The problem with "porcelain" like this is that it's invariably opinionated, and sometimes I'll want to do things that the simple, opinionated workflow doesn't allow for. And you still need to learn how Git works, which isn't really that difficult for someone who already understands the concept of a linked list, i.e. any competent programmer.
I personally like git-flow, but this is just a symptom of git inconsistencies, like git branch and git checkout both work with branches.
I think it would be very useful to have higher level git that would be adopted as standard interface.
First of all, these verbs are only marginally more intuitive than the existing git verbs. Git when it is confusing, is confusing because of the underlying interactions and concepts, not because "push" is too bewildering compared to "sync".
Second, is the global "tower of babel" noise that widespread adoption of this alternate vocabulary will cause less than the slight local reduction in noise from legit?
No. Basically, this isn't a good idea and I really really hope no one adopts this.