I must admit I'm a little bit confused. It opens with a discussion that people find Git hard to use, and a statement that these problems are likely more than skin-deep but then goes on to describe a wrapper around Git which is mostly a bunch of aliases. Don't get me wrong, I'm know that many people do find Git hard-to-use, but I don't see anything in the eventual project implementation which backs up the original claim that the problems are conceptual. I don't think it's possible to fix conceptual problems in a tool by just wrapping it.
I have heard people complain about the staging concept (personally I find it useful, because you can do 'git add -p' which allows you to craft intermediate commits or to-be-squashed fixup commits after you've finished some development), so it's removal in this tool is unsurprising. And it is nice to auto-stash on branch change (though personally I think that they should've made stashing a much better-supported concept in their Git wrapper -- I've never really liked how stashing was implemented in Git).
I do really like that they appear to have worked hard to remove all of the super-scary warnings that Git likes to spit out. As someone who has taught high-school students how to use Git (among other things), I've learned that the easiest way to scare away people from your project is to have bright-red warnings in response to a user doing something. Most students describe it as though the computer is effectively screaming at them. Some tools over-compensate for this is and spew emoji in response to user input, so I'm happy this tool has struck the right balance.
In my own experience, https://www.sbf5.com/~cduan/technical/git/ makes all the difference in this world. The main complaint still remains: the CLI UX (yes, CLI has a user experience!) is really bewildeirng because switches change commands in really, really significant ways, so much so they ought to be different commands. And operations have totally different ways to express "work with repo only" "work with index" "work with working tree". And then git reset does not touch your working files but git reset --hard ruins your day unless you build a safety net: https://gist.github.com/chx/85db0ebed1e02ab14b1a65b6024dea29
Back to the tutorial:
> you can only really use Git if you understand how Git works. Merely memorizing which commands you should run at what times will work in the short run, but it’s only a matter of time before you get stuck or, worse, break something.
> Half of the existing resources on Git, unfortunately, take just that approach: they walk you through which commands to run when, and expect that you should do fine if you just mimic those commands. The other half does go through all the concepts, but from what I have seen, they explain Git in a manner that assumes you already understand how Git works.
I could never understand the complaint that Git is "hard to use". Having used a plethora of version control systems over many years, I never found Git to significantly more or less complicated than any other system. Version management includes many use cases, some of which are inherently complex. Therefore any version control tool must be able to perform both simple and complex tasks, and the latter ones will obviously require a more complicated syntax and conceptual model.
In any case, we are supposed to be professionals. Complaining that Git is hard to use is a bit like a machinist complaining that a CNC machine is hard to use. If you want to accomplish non-trivial things in any field, you have to be prepared to deal with some level of complexity. /rant
>I could never understand the complaint that Git is "hard to use".
It uses horribly unintuitive metaphors and has weird cryptic methods for doing common, simple tasks that practically require the use of google unless you've memorized the UI.
There's a reason that there is a plethora of wrappers around the system (most of them not very good, unfortunately :().
>In any case, we are supposed to be professionals. Complaining that Git is hard to use is a bit like a machinist complaining that a CNC machine is hard to use.
Gatekeeping is the real reason why git's shoddy UI is tolerated (possibly even celebrated). Knowing and memorizing its quirks is seen as the mark of a "true" professional software developer.
>If you want to accomplish non-trivial things in any field, you have to be prepared to deal with some level of complexity. /rant
I don't agree. 99% of git usage on a project involves a series of repetitive commands following one of about < 8 different workflows per project. I'd rather actually use a high level tool that allows you to build and use these workflows on a project by project basis, but sadly I've never really seen a good tool to do this.
Such a tool would also open up git to non-programmers, allowing easier collaboration. I'd love to see managers tweak configuration properties via git, designers push assets, copywriters push copy and translators push content. I wouldn't have to be the go-between on all of this stuff.
The language is part of the reason its so confusing. Why is called a commit? Makes no sense and is confusing. The commands should be obvious by looking at it. Why does someone make a pull request? It seems backwards as people push to a repository.
And then there is all the flags. Why in 2018 are we not writing full words?
Linus is a genius, but he makes things that works for him and without much consideration for others. This is just human nature I think.
The way I see it the Git nomenclature makes much sense.
You "push" to a repository, if it is yours, but you cannot just push to the repositories of others. You make a "pull request" for others to fetch changes from you.
Commit is a "commit" because you "commit a change" as in make something new which differs from the previous state.
"Rebase" just puts your commits on top of the other branch, using the other branch as a "base". (It helps to think of the graph structure)
"Branch" is a branch because what you have is a kind of tree of commits, often more or less a straight line if you've done it right (IMO), and when you make something to work with you deviate from this other history of commits by branching off from it.
I mean it is rather standard terminology, and most importantly, it makes sense. Don't get me started with e.g. Clearcase which frankly makes no sense and should be killed with atomic weapons from low Earth orbit (or any orbit as long as it does the job), just to be sure.
As for hard to use, I never understood this either... I usually use a handful of commands and get things done just fine. If I ever feel like absolutely having to use some kind exotic merge with --onto and looking up octopus merges and whatnot I am probably doing something wrong.
There are plenty of good Git resources available, for example https://git-scm.com/
My perspective is this. I am a quite experiance CNC operator and have used this particular model for over a decade. I don’t have a problem with it, even though I admit it took a bit of getting used to originally and I still agree that the controls aren’t intuitive, but that doesn’t matter to me cause I know them by heart... but now I’m running a shop with 5 other CNC operators who constantly break the machine and shut down work for trivial completely non problems like John used Peters Machine and now Peter is back so John is back on his own machine, suddenly none is able to turn on their machines so they’ve all started cutting out parts by hand. So I’m spending tons of time dealing with complete bullshit things that would not otherwise have been a problem had it not been for this particular brand of CNC. It doesn’t matter how well I personally know the machine, because the problem is that I’m now wasting my time trying to prevent them from wasting theirs. This is not a problem of inexperienced operators, it’s a problem with a machine that only works with the aid of a super-user, and which doesn’t easily show the path of how people should develop super-user abilities without breaking stuff and working really hard to understand what they broke and why before they can move on to fix it.
Thank god I’ve never had to deal with a CNC machine like that. But git is that machine.
Secretly I think this is the true reason for gits popularity. It’s like vim, a wonderful tool once you get past the first hill, but I would never force a whole team to use vim, I know it would be a disaster productivity wise. But because of gits popularity it is indeed forced on almost every developer.
> But git is that machine. Secretly I think this is the true reason for its popularity.
I think it became popular because it was written to solve the needs of the largest collaborative project in the history of mankind (Linux). It was objectively better for that job than any other tool that was available at the time (and thus for many such collaborative projects), and that's where the popularity came from.
Now, does it have warts? Yes. I don't agree that it requires very detailed knowledge to use effectively (if I was able to figure it out as a high-school student, I'm certain that it's not beyond the majority of developers). I think it's just that many developers don't feel the need to learn how to use their tools effectively, and if a tool isn't as-easy-as-possible for simple tasks (which I will admit is the case for Git -- the index concept appears to really throw people off) then it is seen as being "too hard".
In your scenario, using a CNC machine is a key part of their jobs as CNC operators -- so I would expect that learning how to use the CNC machine they use for their job would be an important part of working there. Similarly, developers who use git daily (and is a central part of their work) really should put the time into learning how to use it effectively (it wouldn't take more than a weekend with the right resources). I don't think it's reasonable to say that a developer whose job it is to use git should not have any burden to learn how to use their tools, and that it's the tools fault for being hard to use.
I don't disagree that the on-boarding with git and some of the UX (such as stashing) is quite bad. But it's nowhere near as hard as people make out, and at the end of the day if you want to use something you should learn how to use it -- just because you can get it to somewhat work after 10 minutes of bashing at your keyboard doesn't mean you shouldn't spend the few extra hours to actually understand what you're doing. git is a transferable skill, and the time taken to learn how to use it pays off very quickly.
To reinforce your point - I have worked with people in the past, mostly older, that struggled a lot with Git when all they were trying to do was something simple like commit some static files generated from third-party software to my project. These people only needed the bare minimum (stage, commit, push) of Git yet found themselves baffled and fighting with the tool because of all the possibilities and things it could do that they didn’t really need.
There's a fair amount of tools capable of manipulating a Git repo, not all of which are `/usr/bin/git`. "Everybody must use this complex CLI power tool, therefore people struggle" is simply untrue here, in the premise.
Try managing a massive set of inter-dependent repositories too big for a mono-repo with git, then you will know "hard to use". Your only real choice in this case is submodules, and those bring in an additional layer of pain.
There's also "repo" from Google. And many other tools.
Git is not a panacea for bad design. If you have interdependent repositories (I read that the same as a cyclical dependency, A needs B needs A), then you should fix that first. I mean, if you have the described setup, you will have other problems too...
No, you also have the choice of using separate repositories, and just connecting them with dependency lists. I never understood the obsession with putting hundreds of millions of lines of code¹ in a single repo. Whatever happened to decoupling?
¹ Git can handle dozens of millions, as shown by the Linux kernel
I'm now roughly one year into my experiment to not use the index. I made some aliases to do that. My conclusion is: The index is unnecessary complexity. Amend to commits instead.
My aliases do not work cleanly, so I don't want to advertise them. Still, a git wrapper which removes the index would be an improvement.
By the way, can we still call it "porcelain" or is that outdated?
Conceptual problems themselves may be shallow, deep, or both. Wrapping machine code with assembly makes it easier to use but doesn't fix nasty issues with lack of memory boundaries.
Conceptually programmers having to mentally convert every line is poor ergonomics and will reduce speed and increase errors. Going to labels instead of numbers is an improvement even if shallow and able to improved upon further.
Well I'm definitely not a git expert ( i guess I should just invest more time into it). But was wondering the other day. Isn't GIT "as good" as its(source control) going to get ? Giving the problem its trying to solve:source control,distributed teams/repo's, branching etc... I mean what comes after GIT ?
There are some projects that aim to improve the merging model of Git, such as pijul[1]. Git uses "three-way merge" and it is fairly well-known that the repository state you end up with for non-fast-forward merges (merges that need merge commits) is not necessarily well-understood in all cases. Pijul uses a more efficient algorithm that has well-understood merge characteristics, and is designed around patches not repository states (which means that conceptually patches are the core -- rather than in Git where patches appear to be core but are actually all generated on-the-fly).
It should be noted that Git was not unique in its design. There were many source-control systems that had the same model that pre-dated Git, it's just that Git was fast and significantly easier to use than the other tools. The previous tools would not have been usable for developing Linux, and so Git was obviously necessary.
I took a quick look at the list of commands and they looked so similar to the primary git commands I use that it seemed like a waste. Better to just learn how to use git.
If anyone wants to know what it is like working with a "hard to use" revision control system then I highly recommend trying out IBM Rational ClearCase [1]. Or as I lovingly used to refer to it as Irrational ClearCase. To be fair, I have not used it since 2009, so perhaps it has been improved?
If you use emacs and you find git difficult then please try out magit [2]. I actually really like the git cli, but I use magit a fair amount also. Plus, emacs is awsome :-P
I used ClearCase 3 years ago and this is spot on. ClearCase is little better than keeping revision history manually by zipping old versions of files. I sometimes wonder what kind of insane mind came up with its workflow.
First of all, to checkout a branch, you don't simply select its name. You need to write a freaking configuration file to tell CC what you want to checkout. And it is entirely possible to accidentally write that configuration file in such a way that you'll have half of repository checked out from one version of code, while the other half is checked out from another version of code.
Then there is history of changes. Or in case of ClearCase: histories of changes. Because there are many, in fact as many as there are files. Yes, each file has its own history of changes, completely independent from other files. So if you make a commit which changes 10 files, CC will create separate commit for each of those 10 files, each with the same commit message. Needless to say, browsing history with same commit messages repeated tens or hundred of times, is quite an adventure.
Oh, and because of that, it is not possible to simply checkout some old version of code. If you are lucky, you will have put labels on all files of needed version of code, so then you can checkout that label. Otherwise the only option is to checkout based on dates of commits, and hope that your provided date won't actually cut any commit in half.
The model is fairly similar to CVS, which also keeps histories of files instead of a history of the repository. The ability to have half of your repository come from one "branch" and the other half from a different branch is actually seen as a feature. This enables workflows similar to what you can do with submodules in git.
Having to manage your config specs and the inability to go back to old versions of your software (or in fact just have something reproducible for your build servers) unless you meticulously label everything makes Clearcase of course barely useable. It gets extra interesting if you use multi-site Clearcase and your replicas stop synching.
No, it has not improved. I last used it around a year ago at a company where a lot of young engineers had to pick up a 20 year old code base. Suffice to say, the expertise for ClearCase really wasn't there and it was an absolute mess.
Once upon a time, I remember having to use Visual Sourcesafe, and it started silently corrupting the repository after 2 Gb. Probably some length somewhere was a 32-bit signed variable.
I remember that the corruption was silent. That was bad. But nowhere as bad as Clearcase was in general.
Clearcase is like the bastard child of a barrel of horseshit and a mountain of self-inflicted hurt. One had to use "views" of which there were two types, and some kind of special mount point where the view loaded things from a source repository, given a "config specification" which defined from which versions (branches?) files should be loaded. Making a branch took a huge amount of time for a non-trivial source repository. It was "take a coffee" long time. Sometimes the views went bad. I don't luckily even remember all the problems, this was over 10 years ago.
The config specs seemed somehow to defy logic. Something always broke with them. Usually one just copied premade config specs made by someone with a transcended mind who seemed to have somehow figured out the underlying logic.
And... I can't just put to words how bad Clearcase was (is?). That is my experience with it, and I will without a doubt choose Git over VSS, SVN, CVS, RCS, Clearcase and whatnot any day.
it has not been improved or even updated in but minimal ways.
i am surprised you did not experience the intellectual delight of using the ClearCase 'config spec' with it's ability to use rules to extract the source baseline you wish to work with. In all seriousness, it is very flexible and allows significant innovation in baseline management.
In 1995, it was state of the art and revolutionary. Today a bit clunky and off the mainstream. Compared to CVS it was a very sophisticated tool.
The 'visual tree view' it provides is still very good, even today.
(note: i don't really like it and will not mind changing to a different system sometime this century)
ClearCase was my first VCS and I couldn't agree more. Compared to that nearly everything with git is easy and few things aside from complex merge conflicts / unstashing conflicts are difficult.
Curious as to why - What usecases do you have for staging? Why does sourcetree make it better? To me it's just an inconvenience and a redundant step on the way to committing stuff.
I get that you can use it for partial commits of in flight work but that's never something I've needed in practice. Usually I just want to commit everything I'm working on at once.
Incremental staging of the next commit is absolutely a valuable feature.
I'll often touch multiple files over the course of a few hours, sometimes for slightly unrelated changes, and then want to pull apart the changes into several smaller logical commits. Sometimes a couple hunks in a file might need to go into Commit A, while others go into Commit B.
You can do piecemeal adding of hunks via the CLI, but the interface is horrible. Being able to simply click "Add Hunk" in a GUI is incredibly valuable (or even in some cases shift-clicking a couple lines and "Add Lines").
You can get that kind of interface without a staging area. TortoiseHg would do it using Mercurial's shelving feature (similar to git stash) and IMO that was simpler to understand than staging. In particular, I liked that at all times there was a correspondence between the current working directory and what was being commited. It made it easier to run tests.
I would hate to be restricted to a GUI tool to achieve what git add can do from the command line. Using stashes would be just reimplementing the index using less convenient UI.
I really don't understand what's so difficult about the index... It's just the stuff you will be inserting into the repository when you next commit. Having it separated enables a very convenient workflow that would've required manually using patch and diff when using tools that don't support you.
Git is more than just revision storage. I like to think of code as clay, and the index as a tool you use to mould that into the final construct that gets baked
> I would hate to be restricted to a GUI tool to achieve what git add can do from the command line.
I don't quite understand the use of the command line for git or hg.
In my typical workflow before I commit I want to quickly review all the changes I just made. With the GUI you have a list of files and when a file is selected a diff of that file, without opening a new window. That means you can browse all the diffs in a few seconds just by moving the cursor along the changed files. If you see an unrelated change that doesn't have an impact you can just uncheck these lines to remove these changes from the commit. Or uncheck the file itself if all its changes are unrelated. I feel I'm much more confident of what ends up in the commit than using the cli.
I often find GUIs restrictive because they don't lend themselves well to ad-hoc scripting. I also don't use GUI editors, so that may be a part of it.
I can see how a TUI/GUI for being able to quickly stage things from the UI is useful, but it doesn't make the concept of the index useless on the command line either.
Using git from the command line is second nature to me at this point, and the index is a large part of my workflow. When I use git for revision control (as opposed to eg. Subversion. Or anything that doesn't have lightweight branching, something akin to an index, and rebases), it feels like the tool is helping me organize my commits instead of just being a place to shove things after I'm done coding.
I have a different workflow in TortoiseHg than ufo. In your terminology, I only consider revisions that have been pushed as being baked, while unpushed revisions are the clay. We already have tools to manipulate revisions, while the index, stash/shelve and patches are all just reimplementations of revisions with less convenient UIs. I just go ahead and commit whenever I like (without having to stage!), and sort it out afterwards with a combination of update (like git checkout), revert on specific files (like git reset --soft), and rebase (like git rebase!).
You might say this is trading one complexity (staging area) for another. But you need to be familiar with these commands anyway, so you might as well use the same things for other tasks. Plus, they're visualised on the same revision graph as everything else (e.g. "oh look, one month ago I saved that private commit").
Mercurial has a few properties that make this easier than in git. For example, there is no concept of detached head / garbage collection; when you save a commit, it is simply saved forever unless you choose to forcably remove it. (I have never found myself wishing for Git's refs and heads; they are just straight up unnecessary.) But I could imagine a git wrapper that had these properties too (e.g. when I checkout an old revision, it automatically creates a new branch with a special name that refs the commit I'm leaving behind).
(PS: Having said all of this, 90% of the time I just go ahead and commit and push everything, and 90% of rest of the time it suffices to just untick the checkboxes next to files that I don't want to commit before clicking the commit button in TortoiseHg. This is massively easier than any of these strategies, and it's opt-in. I'm sure there is a command line way to do this but I find a GUI is great for this task because it's quite visual.)
> Mercurial has a few properties that make this easier than in git. For example, there is no concept of detached head / garbage collection; when you save a commit, it is simply saved forever unless you choose to forcably remove it. (I have never found myself wishing for Git's refs and heads; they are just straight up unnecessary.) But I could imagine a git wrapper that had these properties too (e.g. when I checkout an old revision, it automatically creates a new branch with a special name that refs the commit I'm leaving behind).
I don't get it. What does mercurial have instead of refs?
HEAD in git is just one kind of a ref; differentiated from a branch only by when the tooling updates it (ie. when you create a commit in the checked out branch, or when you check out another commit)
"branches" are mutable references. "remote" branches are just refs pointing at the commit that was the remote branch the last time you fetched it to your local repository. They're all the same thing in the end, though.
The way Mercurial branches seem to be a special thing instead of a property of the structure of a repository is partially why I prefer git.
In git, the fact that a "named branch" is actually just a ref to a particular commit that gets updated occasionally makes perfect sense to me. The way mercurial does it has never clicked; why does a branch have to be something special?
I mean, in git, a branch that has no ref pointing to it is still a branch, but if you have no reference to a commit, why would its existence matter? Sure, you can end up "losing" commits when working with rebase, but no-one actually leaves their repo that way if the commit was important; you just look it up from the reflog and give it a name again, and it won't get garbage collected.
And after a branch is merged, why would you keep around a named reference to a branch head that no longer matters? IIRC mercurial has a feature to "close" branches, but I don't understand why that even needs to be a thing? In git, you just delete unnecessary branches (that is, refs), and you're done.
Maybe I misunderstand how mercurial works, but I've not found a source explaining the rationale behind why it works this way.
For Mercurial, you need to totally abandon the idea that a branch is stored by reffing a commit, and the branch is implicitly defined as the ancestor commits of that head. Instead, every single commit has a branch name baked into it as a simple string; a branch is defined as all commits whose branch name matches that name. To open a new branch, simply make a commit with a branch name that hasn't been used before. By default, the branch name of a commit is the same as its immediate ancestor.
When you switch branch in Mercurial, in principle it simply looks through all commits to determine the latest one with that branch name. In practice I'm sure there is a cache of this, which is the closest there is to git refs, but that is totally transparent. All commits must have a branch name, and the first commit’s branch name is usually "default" (equivalent to git's "master"). That close branch feature you mentioned is a special type of commit that stops that branch from being included in the list of branches, but the branch still exists because all previous commits to it still do.
This has a few consequences compared to Git's branches, which may be good or bad depending on the situation and your personal opinion. One is that a commit cannot be a member of more than one branch. Another is that branches are far less mutable than they are in Git; to change the branch that a commit is in you must actually destroy and re-create that commit (e.g. with rebase).
Another consequence is that it is fine for a branch to have multiple heads; just go back to a slightly older revision and commit again. Or, more commonly, pull after making your own commits and find someone else has committed to the same branch. (If you prefer: find that someone else has made some commits with the same "branch name" metadata.) Usually this situation is only transient because you would merge or rebase. Indeed, you cannot create multiple heads for a branch on a remote repo unless you force push, so you'd normally merge/rebase before pushing.
Another bit of commit metadata is state: public, draft or secret. Commits are draft when you create them, essentially meaning "not pushed". Public commits are ones that have been pushed to or pulled from a remote repo. In git, to see what things look like on the remote, you’d use the remote ref; in Mercurial, you’d look at the public commits. Admittedly you lose the ability to understand which remote repo a commit was seen on, whereas git supports multiple remotes. (During a push, Mercurial will still check whether “public” commits are on a remote repo and push them if necessary.) You can mark a commit as “secret” and then it will not be pushed unless you change its state back. This is what I use when I commit something for my own reference later on, which I was talking about in my previous comment. Often when I rebase, I leave the original commits behind and mark them as secret in case something goes wrong.
I can see you think branches are "something special" in Mercurial. Maybe in Git you could use refs to implement something totally different to branches, whereas in Mercurial you're stuck with that exact implementation. But refs seem like an unnecessary implementation detail to me. I never want to implement something similar but not quite the same as branches; I just want branches to work! And by not having any refs whatsoever the system seems quite a bit simpler.
Thanks for the explanation. I don't think it's a good idea, but it does clarify some things.
In git, a branch is a branch by virtue of being an actual physical branch in the data structure.
To elaborate, I think a branch having multiple heads is not really a good thing, since that leads to the actual structure being one or more branches (each point of divergence results in a branch in the commit lineage), but only one name to refer to the collection of commits making up those branches. That abstraction doesn't agree with me.
Since a branch (a lineage of commits) is unambiguously defined by its head commit, having a named ref as the branch abstraction makes more sense to me. I don't know how it could be any simpler.
It makes sense as a tool that should be available. It does not make sense as a default hoop everyone has to jump through. The way that stash, index, working directory and branches interact is completely non-obvious and induces a lot of accidental complexity
As far as I can see the use case you describe is actually covered in gl commit.
"git commit -a" will skip staging entirely if that's what you'd like to do. Should "-a" have been the default? Maybe, but that doesn't mean that you can't use it.
Now, if you want to exclude certain files from a commit I will freely admit this is a pain. The easiest way, especially if you have loads of untracked files you don't want to commit, is to do:
Which is pretty awful, I will admit. I had an alias to do this a while ago (without the need to amend the commit) but it wasn't great fun.
However staging is still a useful concept, and "gl commit" as far as I can tell doesn't really allow me to do something I do quite often ("git add -p" to add partial hunks of a change to staging for a commit). I recognise that I'm probably in the vast minority (outside of the kernel community) when it comes to my Git usage, but staging is definitely quite important for some Git usecases.
What is tortoisehg doing when you check/uncheck files for commit? I think you can even check/uncheck individual hunks in the diff interface next to the changed-files list. I don't think it's shelving unmarked changes, the changes are still there on disk.
It looks like mercurial has a staging area, just that the default it to stage everything unless the user says so, rather than the other way as in git.
Funny that people are mostly unaware of mercurial supporting this - I would argue not using it by default it pretty user friendly, so long as you know it's there when you need it. I use it pretty often, but it's nice not having the boxes unchecked by default. I usually do want to commit everything.
Relatedly, totoisehg is the reason I don't use git for my personal projects. No git gui that works on Linux comes close.
I split file changes into multiple commits all the time. That alone makes many diffs much more readable and changes easier to follow, even if it results in occasional git-log clutter.
What is the redundant step? Do you not use "git commit -a" -- or does it not work in certain cases?
Staging is quite useful if you want to create several commits (perhaps fixup commits, perhaps whole commits) based on the current repository state. This is why you can do "git add -p" to add parts of files to staging.
You mentioned later in the thread that you prefer stashing -- but Git doesn't let you stash certain files (you have to stash the entire state), and in addition stashing has a much more awful UX than commits (it's represented as a stack which means you have to pop elements off it -- and you've then lost that stack entry and you can't pop the stack with uncommitted changes). If there is one aspect of Git's UX that needs to be massively redesigned it would be "git stash".
Don't partial commits run the big risk of commiting code that may not work, since the partial commit on your own computer will be tested against your working tree, wheras after it's committed it run with a different view of the files?
It could. OTOH, most workflows I've seen use the approach "do whatever you wish in your repo and in your branches, but merging requires that the tests pass on a CI server, which only has access to the repository and has exactly zero uncommited files.
In other words, go ahead and break your builds six ways from Sunday, but they won't get merged until they pass based solely on the state of the repo.
Not if you know what you're doing. For example, say you added a bunch of TODOs and FIXMEs you noticed in existing code while working on something. Now, you're ready to commit. The TODOs and FIXMEs don't necessarily correlate to the code changes you made. Should they all be committed with the code?
Using the index to stage and commit hunks separately lets you easily add and commit the unrelated TODO and FIXME comments separately from the code. A tool like Magit makes it trivially easy to do.
And since they're comments, they have no effect on tests or the code.
Just to play devil's advocate, to achieve this always-working guarantee you could: stage, commit, stash your working directory, test your code, and then unstash.
Most of the time I'm doing partial commits it's because of squashing them into older commits via rebasing. Rebasing allows you to run an arbitrary command (e.g. your test suite) after each step and will pause the rebase if it returns non-zero.
Maybe it depends on what you're working on. I often have to try multiple things to see what's working. During that process I slowly stage things that are already working and then move on to the next part. Before the final commit I often discard things that I changed but didn't turn out to be necessary.
Maybe there are other ways to do this but for me it's the perfect workflow.
It is common for me to have miscellaneous changes I don’t want to commit, but I think this is problematic on my part, and I shouldn’t typically be doing it. The only defensible version of this I can think of offhand is changes that are necessary to get the repo to work in my local, but which I am not yet able or willing to commit and push.
It depends. If you have, as we do at my work, a pre-commit hook that runs acceptance tests on each commit, and if the changes you've made are to get it to work on your local, then leaving those changes in for the test run is really the only option.
Should I get those changes committed? I should. But that involves a lot more testing and thought, since it still has to work for other people with different local dev setups.
Interesting. It seemed to be just git-renamed, but the concept of "no staging area, smart-add everything" and "autostash everything on branch change" looks useful. Not as powerful as git, but it's always possible to fall back to non-abstracted git.
I feel like this is just another "git is hard so lets make it easier" program that makes collaborative development a pain. maybe its just my puritan work ethic.
first we had git, and anyone who cared to spend the time could pick it up and understand it well enough to use it. Then we got github and gitlab, which made remote branches more manageable but introduced and entirely new class of developers who only added code through the web interface and emailed/called when they needed a merge or just merged to master because you were sick of the hand-holding.
then we got the GUI clients for windows, which resulted in armies of programmers who didnt understand keys, or authentication, or why the gitlab/github server existed but just wanted to commit their code and as a result left the codebase with a graveyard of rebase --hard and reset head garbage that had to be explained later. supporting them became a nightmare of screen sharing and shouting.
finally we have gitless? and developers now have to keep straight gui, console, gitlab/hub and some asinine wrapper script between the teams? so when jack commits with his GUI and accidentally drags and drops 3 branches, while jills gitless command wiped half the unprotected master, how does it get sorted out?
Git was not first, and it arguably didn't achieve its dominance based on technical superiority. It almost certainly didn't achieve that dominance based on offering a better learning curve or a bizarre interface choice, even though I might personally understand and appreciate the relative tightness to its underlying systems. I also don't think we should defend a technology or tool by portraying it as a sort of null-hypothesis, a default automatically suitable for anyone except in special circumstances.
I'm currently making source control recommendations for my new client. No one there is a full-time programmer, and they mostly do engineering and PLC work, but more recently they have to work with higher level languages from time to time. They absolutely need something they won't have to fight to learn. Other times I've recommended source control during my career include tutoring first-year/some second-year university students, who are often still only becoming familiar with programming and CLIs, and for whom Git seems both arcane and stress-inducing, two things you absolutely don't want from a source-control system.
I am adamant that in neither of these above cases would git be the right choice. I'm also not convinced its the right choice for many development companies, which often have staff of a range of skill levels. I'm lucky in that I've nearly always been working with passionate programmers, where we can and do happily make the choice to adopt git without a second thought.
Git did beat both of the other main contenders in the DVCS space (Darcs, Mercurial) hands down when it came to performance around the time it rose to prominence, so I think it's unfair to say that it had no technical superiority.
"Didn't achieve its dominance based on technical superiority" - I partially disagree. Compared to SVN, Git was superior in multiple aspects. Perhaps it was not The VCS To End All VCSs, but lacked the annoying warts of CVS and SVN. (Mercurial does have some nice features, sure - but wasn't quite there when Git was on the up-and-up)
Funnily enough your complaints also completely ignore what gitless actually is. It does not hide the underlying git structure, it just exposes it in a sane way. Check out the research papers. It's really well thought out. Same power with less exposed state is to me the definition of good software design.
I don't teach gitless to novices because all the rest of git tooling uses the original git vocab. Unfortunately we seem to be locked into using the bad interface design of the original git forever and ever, along with the chorus of people who claim it's perfectly intuitive (once you spent a few thousand hours debugging user errors).
I have a fairly advanced knowledge of git (that is, at the level of porcelain and plumbing commands; I haven't touched the C codebase itself) and I intend to give gitless a try when I get back to work on Monday.
My reason is that, while I'm a fan of git the technology, I think the default git CLI is an unmitigated fucking nightmare and I begrudge every neuron of space that I have to waste remembering how it works. Unfortunately, none of the graphical tools I've tried are as good. So I'm eager to try an alternative command line porcelain that's not so completely batshit insane. If it works out, maybe I can reclaim some of that wasted space.
- Command line switches are inconsistent. For example, to list remotes you use -v but to list branches you use -l
- Speaking of command line switches, how about that bizarre need to separate paths in certain commands with "--" so that the parser doesn't get confused? I can never remember when that's necessary.
- There's weird overlap between the porcelain commands that make them harder to learn than they should be. For example, git checkout can do the work of git branch. git pull usually does the work of git fetch. Some common operations get their own commands, while others require you to use switches on other commands. It really shows that git evolved organically from a bunch of shell scripts used by one particular dev team until it katamari damacy'd into a big agglomeration of random parts.
- Poor defaults, such as git push --force not having the behavior of --force-with-lease, and also git push pushing all branches at once by default.
- Many of git's mechanisms are overly complex and lead to a depressing number of bewildered users. E.g. witness the confusion and conflicting advice at https://stackoverflow.com/questions/6089294/why-do-i-need-to... Another example is git reset, which is invariably a nightmare to explain to an intern or new developer who hasn't used git yet. Trying to learn what git reset does from reading the man page is like trying to learn calculus by examining the digits of pi.
Firstly, I agree that Git has a learning curve. However, trying to learn anything based on man pages alone is not a good idea, in my opinion man pages are for reference and not a substitute for more extensive documentation. Of course, sometimes man pages are the only document one has, but this is not so in the case of Git. I myself am not a Git expert, but after reading about what problems people have with Git, it feels like people should perhaps not go for the most exotic commands by default, and they should use a topic branch based workflow. And they should read the Pro Git book and I mean this in a good way :)
As for the switches, one can just as well use "git branch -v" to list branches, I usually pipe to grep if looking for a branch. For the "git remote", it actually does show you the remotes without any switches, but the URL of the remote is not the remote... To see the URLs you'll need the verbose switch. Maybe this is right, maybe not, I do think it makes sense.
The two dashes is actually not a Git peculiarity. It comes from getopt and POSIX.2 to signal the end of options. Compare with e.g. to rm a file that's called "-rf", you'll have to do "rm -- -rf" in the shell.
As for the intern, just tell them "Git reset moves backwards in commit history". Of course there are details (and you can get back to the future with e.g. git reflog), but it should be accurate enough description to an intern who is new to Git, since that's what "git reset" is mostly used for anyway. IMO "git reset -p" and such are somewhat advanced usage.
The problem with the Stack Overflow link is that Git is not tracking that upstream branch, just because the local and remote branches happen to have the same name after a push does not mean they are the same and should be tracked. I'd argue that if one works with topic branches, that kind of situation is kind of remedied automagically through the workflow... Anyway, Tzen's answer there is the correct one (when including the typofixes in the comments).
Also, thanks for the link to the Git man page generator, it's great!
Because they have a lot of other things to deal with. I have enough other things I have to learn and I simply don't have the time to become a git expert.
Finally gave this a proper read. It's a bit disappointing indeed. Besides removing the index (which, as other commenters have pointed out, is questionable), there is one BIG change from Git to be noted:
You can always switch branches, without losing your working directory changes. In the common case, this amounts to automatic stashing and unstashing, enabling you to quickly move around to an alternative repository state to check something out (with real git, this is too annoying and I resort to browsing the history on github more often than not).
The second case illustrated in the comparison section is switching branches during a rebase, which git doesn't support without aborting the rebase.
My recommendation: if that seems like a killer feature to you, use gitless. Otherwise, the slight simplification of commands isn't worth adding a layer on top of git.
My biggest problems with Git are that it doesn't handle large binary objects efficiently, and that it's difficult to treat multiple git repos as a single repo (useful for many things, including keeping versions coherent).
It may, but it's a hassle to set up as it requires a separate server daemon (for which I don't understand the necessity, as a git repo itself can be stored on a server over ssh).
What I see this seems to be doing is auto-staging every file that changes? And beyond that it has a few aliases for some commands. Is anyone else getting the same thing?
I use git in my CMS which auto-commits a template file (text) on save. Which works great in a browser editor online. (ie, editing files remotely)
But I am not seeing an advantage to "not staging" with local files. What does this save when working locally?
Is there some disadvantage to staging I am not seeing here? Changing to "not tracking" seems like you removed the file from the repo, which in my opinion goes against the grain on how git works, and in a sorta bad way.
> 1. The redefinition of “tracked” and “untracked,” and the
elimination of “assume unchanged” and the “staging
area.”
> 2. The redefinition of the concept of “branch,” and the elimination of “stash.”
> 3. The creation of the notion of a “current branch,” and the redefinition of “head.
I would agree that most of the delta from git represents an incremental improvement in usability; staging, stashing, and complex ignore rules are all things that are more likely to get in the way of novice to intermediate git users than help them. That being said, I'd classify those usability issues as minor in the overall picture. Most of them are trivial to smooth out either via git aliases or shell aliases - for example, I've had `ignore`, `show-ignored`, and `unignore` aliases for so long that seeing `git update-index --assume-unchanged foo` on the Gitless site made me realize I'd forgotten that that's what my `ignore` alias is actually doing under the hood.
By far the most complex & difficult aspect of using git (and source control in general) is merge conflict resolution. I'm not convinced Gitless offers much benefit in this aspect and in fact I suspect it may actually make things worse. Complex conflict resolution is when the ability to distinguish between staged and unstaged changes is most useful and sometimes even crucial. Furthermore, while Gitless offering capability to 'pause' a conflict resolution by switching to another branch is neat, I would say it's very rare that I need to ever do so in the middle of a conflict resolution. Difficult resolutions require full concentration - if I find myself needing to switch to another branch in the middle of one, the context switch usually renders me unable to pick up where I left off and I wind up starting over to make sure I'm working from a clean slate.
On the whole, I could see Gitless being valuable in academic environments to facilitate desparately-needed use of source control among researchers/postgrads/scientists. But I would steer clear of it in a software development career as I think it would stunt user's abilities to truly master a core tool of their profession in the long run.
Good points overall, I don’t disagree but I’ll try to give another POV.
I think the focus on stashing is that it’s basically an hidden state. If for instance you switch back to a branch after a while and you don’t remember you stashed, it will just be lost work. Overall I wish stashed were shown as candidate commits, I actually end up making temporary commits that I amend afterward, most of the time.
For the switching between branches during conflict resolution, it might be for people like me who check back and forth reference branches when merging code.
For instance a conflict can be between two feature branches I want to merge, and I’d need to check on master what is the current behavior. Or what’s the behavior on other branches that will need merging as well. Currently I’d just open github/gitlab on the other branches and compare from there, but I’d see the value in switching the local files.
All in all I feel git is too aggressive in making the user deal with all the details when it could have sane non destructive defaults
Yep, I basically agree with all of that. To clarify my main point, I don't think the marginal benefit that Gitless provides for working around these rough edges outweighs the disadvantage of not learning the underlying git functionality and thereby being unable to utilize advanced techniques that are inevitably required in the course of a serious software engineering career.
I like the idea of working with the simple datastore of git - immutable objects pointing to each other - and manipulate them with a programming language.
But there's lots of things you routinely want to do that aren't convenient this way. Still has some appeal.
This was bound to happen. The whole world moved to git without really understanding why. First we started to make "hubs" and bless their copies of the repo. Then people will start to strip and simplify git itself. Slowly but surely they will reinvent Subversion.
Does gitless really achieve the depths of subversion? Judging by the command list it looks like to add more easily understandable commands, some maskin the originals, ethers doing something more elaborate without requiring the use of flags, etc.
(I'm definitely not going to start using this since I already know the real git, but I can understand where it is coming from)
2.50 per cent, that born in Asia by 4.47 per cent, that aged less than 15 years by only
0.46 per cent. Interstate annual population growth rates currently (1999–2000) vary
between 1.7 per cent (Queensland) and –0.1 per cent (Tasmania), while massive differences
exist in the direction, scale and components of population change in
regions and communities.
This paper takes the approach not so much of predicting the future as of exploring
what will happen if demographic trends and tendencies evident in the mid- to
late 1990s continue to evolve in the directions they seem to be moving in. No startling
predictions are made of major reversals of trends. Instead the emphasis is
placed on what seems likely given current trends and patterns in other developed
societies. In many respects Australia’s current situation is in the middle among
OECD nations, and seems to have further to go in some areas, including population
distribution
Gitless doesn't change anything about git's concepts, it just abstracts away some commands. So if you think this solves the problems, they're clearly not "conceptual" faults.
I think this is important because people are so quick to jump on the "git is bad" contrarian meme. Git is a fantastic piece of work and the CLI has a variety of issues. On top of this, git is conceptually unintuitive, so the CLI issues make for a worse experience.
The other half of the issue is that git's commands don't follow the abstraction. If each command mapped to a single dag operation, it might make more sense. But they don't (revert).
They shouldn't. I'm not saying that Git doesn't have commands that can be hard to understand fully, but the whole point of any abstraction is to hide the "insides" of any operation so you don't have to think about them.
Having commands for each DAG operation will just add more complexity and expose a structure which you shouldn't be handling manually.
I think in order to really feel comfortable with Git you have reverse that and think about the DAG as the actual interface and the CLI as the clunky implementation you use to modify the DAG.
I think the main problem is that many developers don't think of Git as a DAG, so they don't really understand at a fundamental level what the operations are actually doing.
Once you understand this, Git really does become simple. All you have to do is map each command to the actual operation on the DAG.
Yeah, but the question is whether a DAG is a good mental model for a VCS. Just because that's the underlying data structure doesn't mean it has to be the user interface too.
Exactly. This seems to be a point that the "Git is easy" crew doesn't understand. Not everyone (in fact, very few) find going into that depth for something that's nothing more than a tool to be reasonable. Reminds me of the Gentoo users that used to say compiling everything is a great idea for an OS.
I find that people understand "linearized" concepts easier than other kinds(DAGs included). When elements are left-to-right or top-to-bottom, you can read what is going on at a glance.
So the next major step in VCS technology will most likely do something to help linearize our views and reduce the tangling that comes into play with any tree or graph structure.
I compare it to 10-15 years ago, when functional programming was rather rare. Mid-level OO programmers would complain it was confusing and unfamilar, whereas in reality has beautiful and simple concepts.
Git's use of a DAG is confusing and unfamilar for many programmers, though in reality it's beautiful and simple.
Pretty much this. Fortunately the command you need is usually a quick Google search away, and a sequence of basic invocations of branch, checkout, merge, rebase and commit are usually enough to transform the DAG however you want, even if there are simpler ways to do it.
It is supposed to be, but I am not sure it delivers on that part. That’s another discussion, but for instance I wouldn’t bet on having a random 10 yo kid understand OO beyond the bare Cats and Dogs tutorial everyone goes through at first.
And that’s what I would say about git as well. Even after knowing the internals and how it is supposed to work, I still feel that for a tool it’s pretty unelegant and puts a significant burden on the user to know what needs to be done in what situations.
Yup, second that. My old boss introduced the whole team to Scala and made us attend a weekly tutorial as part of training/team-building. Since then, I try to write stateless functions, methods and objects as much as possible regardless of language or platform.
Git is quite elegant if one has a good grasp of graph theory.
Git is certainly great technically. But one should not need to know graph theory to source control files. And I believe that any version control system that does not follow the convention (that probably predates Linus' existence on Earth) that commit should actually commit changes to server, is, by definition, more4 hard to use than it has any reason to be.
But this might be a good study in why Linux is not taking over the desktop, and unlikely to do so in foreseeable future.
>I believe that any version control system that does not follow the convention (that probably predates Linus' existence on Earth) that commit should actually commit changes to server, is, by definition, more4 hard to use than it has any reason to be.
Usually, VCS commands makes some sense (i.e. commit commits), which isn't always the case with Git.
THere are only two version control systems where I ever needed to use commands, rather than being able to do what I need in GUI -- SVN (because it is crap and would corrupt repository all the time, and then you needed to fix it up by hand) and Git, because... well, because Git.
I worked with cvs, perforce, clear case, svn and mercurial before git. And each system force me to learn new concepts and a new set of commands. There is no one universal set. There is no surprise your vcs skills are not transfered to git. And no, some inferior wrapper like subj doesn't help you. It's always better to learn tool.
But checkin had always did the same thing, be it in VSS or PVCS. Sure, there'd be varying capabilities, differences in tooling, but concepts were the same. Git wants to be different for the sake of being different (even if we assume for a moment that one should know anything about DAGs in order to use version control, which is pretty laughable by itself).
I bet you have no problem in remembering what git pull, git checkout, git add, git commit and git push do, isn't it? For everyday work it's enough. You have problem in mastering git, all these nifty logs, diffs, indexes, refs, heads, remotes and other stuff. Other VCS have complex concepts too besides checkins.
It's not even remembering whatever non-standard terminology Linus came up with (although when I am feeling particularly curmudgeony I don't even want to know what push is, and why doing a commit isn't enough). It's a) having to deal with it in the first place, because the management decided to cargo-cult it, even though we are not developing anything resembling Linux kernel (there were no issues using TFS before, they just decided that they want to give Microsoft even more money and got a commercial Github account), and b) that I even have to drop to the CLI in the first place for operations that in any other VCS I could do with a couple clicks right in VS GUI. With TFS I had to use command line maybe once a year, and usually for something not strictly necessary. With SVN it was maybe every c9ouple of weeks to fix up the repository it messed up, With Git it is way too often.
Whatever technical advantages of Git are (and technically it is good), I think it fails as a tool to let me do my job easier.
It's a once a month / once a quarter occurance. I'm not sure if it's because of changes to the webservice or not enough financial backing.
I've basically given up on using early access pijul. I've had a problem with each of the last three versions, primarily pushing to Nest. It wouldn't be an issue if I could install pijul on NearlyFreeSpeech (because then I could self host on a known good version). I want pijul to succeed, its patching model sounds good. Clearly, it's working for some group of people. But I'm not one of them, and it's past where I feel like I'm wasting my time. I'll try again when they're v1.0
Git design is surprisingly clean and simple. The main issue of git is its CLI and commands naming. They are indeed unclear. But again, concept behind is absolutely amazing. You just need to understand that git repo is a series of snapshots and after that all other details become clear.
Naming is difficult. Good names suggest the right metaphore to understand something. But for git, there is nothing similar in physical world. "push" "pull" and "merge" seem ok, but even "branch" is an original concept different of its usual meaning. Maybe git should have used non english words to avoid confusion.
Branch seems to fit the dictionary definition: "something that extends from or enters into a main body or source". And in fact, it didn't originate with git, it's at least as old as CVS.
I have heard people complain about the staging concept (personally I find it useful, because you can do 'git add -p' which allows you to craft intermediate commits or to-be-squashed fixup commits after you've finished some development), so it's removal in this tool is unsurprising. And it is nice to auto-stash on branch change (though personally I think that they should've made stashing a much better-supported concept in their Git wrapper -- I've never really liked how stashing was implemented in Git).
I do really like that they appear to have worked hard to remove all of the super-scary warnings that Git likes to spit out. As someone who has taught high-school students how to use Git (among other things), I've learned that the easiest way to scare away people from your project is to have bright-red warnings in response to a user doing something. Most students describe it as though the computer is effectively screaming at them. Some tools over-compensate for this is and spew emoji in response to user input, so I'm happy this tool has struck the right balance.