Occasionally, I'll see articles talk about "fixing" git by eg. removing the staging area, or something like that... but the staging area is great! It's literally a feature I was dreaming about when I used Mercurial.
I definitely think there's room for a more intuitive solution. I would rate the git learning curve as "medium-easy"
For many cases this would be a wrong approach. But git's storage model is quite simple and elegant, and both gives unlimited freedom in adapting it to your needs and could be dangerous if you don't understand it.
When coaching junior devs on git usage I always start with merkle trees, not with a list of commands to remember. This detour takes 20 minutes, but actually gives intuition to fix even worst mistakes without my help when they happen. I can't imagine the same with any other VCS.
It seems most (all?) interaction with the remote is via sync commands: push/pull/fetch. So why bake it into a different command. Commands like "git tag" interact with your local.
Given the abstract concept of a checkout, as it works in git, none of that is surprising (save for maybe that you could create a branch); however, that seems like a desirable feature. Why would you want to do a branch create, then checkout after, when you just want it done right away?
EDIT/P.S. Regarding the git "abstract concept of checkout" that I mentioned, but forgot to define. This is a pretty simple concept: switch working copy to on pointed to by branch reference, and new commits will go on that branch (appended to the end of the branch), create new branch if it doesn't exist (but doesn't this require a flag?)... can't you still create with branch if you really want to?
Git v2.23 (released in August 2019) added "git switch" and "git restore" commands to straighten this up.
If you started out from a blank slate then git's not too bad to learn; I've taught several non technical people to get to the point where they can at least read a git history and have some understanding of what's happening when.
At my current job though a lot of folks came in from CVS, SVN, and TFS and it's been a struggle for many. TFS for instance encourages committing large binaries so when they were migrated onto git, their repos were as large as 50 gigabytes because they have every binary from every release from way back when. I've found they actually need someone to explain why git does the things it does, otherwise they have a very wrong mental model of what's going on. And git's confusing terminology doesn't help at all.
Though once it clicks, it just clicks for the most part.
Cmd+K to commit changes. There's a list of all files changed, organized by file hierarchy. You can click any of them to get an embedded editor and you can edit right from there.
There's a VCS pane you can pop up to view commits from any of the branches you have pulled without switching, you can select commits and right click > cherry pick to pull them into your current branch.
And the diff resolver is perfect. 3 vertical panes with the incoming and local changes on the left and right, and center is the merged product. You can press arrows on each side to bring those changes into the center, it shows right where they'll go with colored highlighting before you even make any changes. And the center is once again an editor so you can just manually type in it to resolve conflicts too.
Git's mental framework is so visual for me, it just seems like a better experience in a GUI. Especially one as well-thought-out and intuitive as what JetBrains came up with.
That menu changes depending on what the IDE finds in the project.
If its generic VCS, then you're seeing things like https://www.jetbrains.com/help/idea/version-control-integrat...
The git menu has options like 'manage remotes', 'merge', 'rebase', 'Reset HEAD' and so on.
Right clicking on the log in git log pane brings up things like Cherry Pick, interactively release from here, fixup, squash into.
And there are things you still can't do on their UI, personally the most missing feature is to remove from git without deleting (from when you need to ignore something already checked). And also a native git reflog, once I discovered it it has saved me on more than one occasion. Can't they add it on the current log as a "show deleted commits" filter or something like that?
https://youtrack.jetbrains.com/issue/IDEA-152437/Make-git-cl...
I've been using version control systems since CVS and I've found git the easiest and most sensible thing to use. Admittedly, some of the commands reflect internal data structures and concepts rather than what a user would want to do but that's just a learning curve issue. To address specific points.
1. Of the 157 commands, there are maybe 10 or so that one would need on most days and maybe 5 or 6 others when things go awry. Perhaps another half dozen for specific workflows but that's it. How many times do people use git daemon or git instaweb or git fsck? Why are these listed there? I do git trainings and teach a handful of commands in half a day which are sufficient to get people started.
2. The index has been extremely useful to me when I code for a while and then later need to commit only some files or parts of files into separate commits. This is a "good thing". The workflow which the author is suggesting would be like a "git commit -am ... && git push" which is not ideal
3. There are two destructive commands. git checkout and git reset when you've not committed. These two can discard uncommitted code in the working tree and you'll lose them. Once you've committed, it's possible to undo almost anything using the reflogs. They're very useful and worth learning how to navigate and use. Even rebase --hard can be undone by switching to a previous reference.
I think this is a deliberate decision. git is a power tool that sacrifices protecting the user from mistakes to give the user fine grained power over a project. A tool that hides these things from a user and tries to wrap the whole thing in a veneer of user friendliness might be good if engineered properly but my feeling that is that it wouldn't be worth the sacrifice.
Highflux itself advertises several things like " Automatic commit on every editor save." which I'm not sure are good ideas. I hit save repeatedly while working. Each one of those saves is not meant to be a commit.
If there would be qualified git technicians, that would take care of all git related activities developers need, I don't think there would be so much complaining.
However, what actually is happening, is dev, still being absorbed in his project, suddenly needs to confront index, stage and cache (these three are one, yet are not the same), figure out whic of the soft hard mixed reset, no, revert to use.
So I want to put my local changes in new branch? Use "git checkout"! But checkout was the dangerous one!? And you "cp -a" your whole dir, because you are afraid to mess up...
Unless you're using submodules. Which is one big reason people hate them usually!
Worth to pause and consider the implication of this statement.
GIT complainers should write their own DVCS :) let's see how many people will use it .. if it would really be better everyone would use it.
100% true. I am one of those devs who never got any formal training on git or was never motivated to RTFM or even WTFYV (watch the f***g youtube video). I simply started using it and many times ended on StackOverflow when I was stuck.
For a very long time I didn't know that you can create a new branch anytime. I used to make a bunch of changes locally only to realize later that I was in the main develop branch. To "fix" it, I used to copy everything to a temp folder, do a "git stash", then do "git checkout -b newbranch" and redo my changes.
For anyone wondering, a great FV if you feel like you are using git without understanding the fundamentals is Git For Ages 4 and Up [0].
Visual Source Safe would outright die when your repository overflowed a 32 bit file.
Changing a wrong commit message was almost impossible with CVS.
I push into the wrong branch and make other mistakes like that sometimes with git and I have no fear about it at all and little stress because I can always look in the cookbook and find the recipe to fix it.
Git also is the basis for numerous tools such as GitHub that are accessible to non-technical users. Git is the only version control system I've seen that can be used like that.
Specifically there are systems which are complicated because they are too complex and others which are complicated because they are too simple (a few simple ideas combine in ways that can get complex, people get confused because they don't see how the simple ideas are related to much more complex compositions of those ideas.) Git is fundamentally the latter.
To explain, Linus Torvalds created git in a very short time when they lost the license for the version control system they were using before. Linus was able to develop such a scalable system very quickly because it is based on simple ideas that are very similar to the ideas used in blockchains.
It has the appearance that it is complex because it has accreted many layers on top of that very simple conceptual core.
Some of the things that git critics universal complain are complex, such as the index, staging, etc. are keys to git's success. Because of that I have very little fear of screwing up. With other tools I would manually replicate that functionality by copying files when I was afraid of screwing up and probably screw up doing that. It is a small burden on the contributor but it relieves a large burden on the maintainer of the system who is not always cleaning up messes.
I find Git simple because I have a cookbook I work from. A better UI would put that cookbook on your fingertips. Look at the Github UI... A UI like that to make changes in a CVS repository would be like science fiction. Trouble integrating version control has been a persistent problem with "business rules engines" and other kinds of tools and Git makes it possible to make a simple interface to say, edit a Wiki that is managed in Git.
Some genius created a git man page generator that creates plausible-looking but completely nonsensical man pages for made-up git commands. The fact that they sort of look right is a testament to how arcane the actual man pages are.
Here's something I posted 7 years ago over on a reddit comment thread about it
---8<---
I've been running a git hater twitter account for years and have had git use me, or me use it, for 8. (https://mobile.twitter.com/githater)
I "grok" the concepts. I do not however, get the broken command line interface. How is an error message like this at all helpful:
git push -u origin master
error: src refspec master does not match any.
That's not even a proper english sentence.
Here's an example of the three counterintuitive undiscoverable ways to do one common thing that everyone wants; be able to push and pull from a branch without specifying it each time.
git branch m
THEN
git checkout m
THEN
git push -u origin m
OR
git branch --set-upstream=m origin/m
Or if you want
git checkout --track -b m origin/m
How do you push to a branch?
git push origin m
how do you delete a REMOTE branch?! Same thing, but prefix it with a colon
git push origin :m
How do you delete a LOCAL branch? Use a different command, with a different option
git branch -d m
Show useful information about tags? What about sorting them, by date. Sounds typical, common if you dare say... If you think it's in git-tag, your princess is in another castle. You need git-for-each-ref. Here's the simple to remember magic:
git for-each-ref --format="%(taggerdate): %(refname)" --sort=-taggerdate --count=10 refs/tags
So easy to use, no wonder it's number 1.
how do you rebase? It's a simple task!
git rebate --onto something commit id that is one before where you actually start from [ space, not 2 dots like everything else ] commit id where you want to end at ...
Great, now you are in a "detached head" state. So the rebase onto didn't actually rebase on to it ... yeah ... about that...
---8<--- (from https://www.reddit.com/r/programming/comments/3qt28h/xkcd_15...)
So in conclusion, the documentation was full of arcane discussions in domain specific jargon. The interface was wildly inconsistent and asymmetrical and the errors were cryptic and unhelpful.
Here's a fun one. If you just git init and then have multiple users start pushing, you know, like the documentation encourages you to do, the objects database files get the ownership of the person pushing upstream and then can lead to wildly cryptic intermittent permission denied errors because the database is actually just a bunch of unix files. Yes there's many ways to fix this, but that's not the point. Why is a deep dive discovery process needed to make basic things work in obvious ways? It's a Heathkit when all you need is a calculator.
When you expressed these complaints people would respond with theoretical introductions to branching and ASCII art diagrams.
It was all no good. I even tried some futile attempts over 10 years ago to contribute to clean things up.
The problem was I was unable to convince people deeply intimate with the codebase that there were hostile user patterns that could be alleviated with a bit of expository writing. All the cryptic jargon was utterly clear, exact and concise to someone who's spent 1,000 hours on the source. "Many people find these interface patterns confusing" was met with "we have academic level documentation with diagrams". Alright. Useless.
It's gotten a lot better though.
Git just chose to expose them inconsistently, making easy DAG operations hard to remember the syntax for.
I'm also not thrilled with the "everything is a pointer" model since that doesn't match how I've seen branches used in practice; Mercurial's concept of a branch as a named, linear sequence of commits seems to better match how I've seen it work at companies small (< 50 people) and large (>50K people). It's not a big issue, but it is yet another impediment that isn't necessary.
The reflog is useful, but not as ergonomic as Evolve's hidden commits that have been replaced.
Everything about Git's UI is like that. Poorly thought out, poorly integrated, causing unnecessary friction on top of what is a perfectly fine underlying implementation.
https://github.com/search?q=alias+filename%3A.gitconfig+exte...
You get some pretty wildly interesting ones like https://github.com/jorge-barreto/dotfiles/blob/7769df698f14c... or https://github.com/zerochae/dotfiles/blob/6f972916228cf13f3b...
Unrelated but also nice is looking at how people bring sanity to tmux https://github.com/search?q=filename%3A.tmux.conf&type= which is how I found out about https://github.com/tmux-plugins/list
Since Git v2.0 (released in May 2014), you can do:
git tag --sort=taggerdateSo then you don't learn how it really works, and you get weird problems because you never formed the right model in your mind.
It's also the case that there's a few commands you use a lot, but a lot of commands that you reach for only in specific cases. This creates the impression that it's too complicated, because as soon as you go off road you get stuck.
There's nothing wrong with the architecture or model, it's the syntax for me.
They have classes for compilers in school, they should have a 1 week class on source control because git makes a lot of sense if you understand the underlying data structures.
- I use sourcetree for committing, it is a great UI tool for seeing your commit graph and just entering commit messages / partial commits / selecting which files to commit
- I use command line for all pulling/merging/fetching/branching etc. Git command line is just so simple IMO (once you get a short intro to it).
- Repairing issues in git is honestly not difficult.
- The hardest part of git is branching, merge conflicts, and squashing. When you combine all 3 is where it gets challenging if you don't know how to avoid any gochas. But it does make for nice revision history.
So I guess if you are doing some crazy complicated git stuff, I can't speak to that. But in 8 years I can definitively say I have only enjoyed git, and have often been the person to debug issues with people using git, and it is always a fairly simple thing to un-screw things up.
Criticism: push -f is definitely a dangerous operation. I can see why the mercurial team said no history rewriting period.
Obligatory XKCD: https://xkcd.com/1597/
Dev experience at Google kinda sucks for the most part, but one thing that works amazingly well is VCS. You never even have to think about it, it literally just works, and it works at very large scale (monorepo for all of Google).
It’s just: 1. Create a workspace 2. Submit the changes in your workspace
And that’s it. I hate going back to the mess that is Git.
Google's primary internal VCS was originally Perforce (https://www.perforce.com/) and when rewritten to scale to the size of their monorepo largely retained the same user experience. You can read about that here: https://cacm.acm.org/magazines/2016/7/204032-why-google-stor.... Perforce's user experience isn't too different from svn. It is easy because it is a simpler model, and was available from Perforce as far back as the 1990s. You simply can't get into the same kinds of quagmires that git allows you to get into. It is also not a DVCS, which simplifies a lot of issues.
That said, Google's internal Perforce clone doesn't offer any sort of stack/queue of local commits that you can send off for review and continue building on. You've got one copy of your edits and that copy is not under any real version control. For a company that highly prizes code review there was always a tension between sending small-enough changes off for review and continuing to make progress on a larger feature. At the time I left a few years ago there was a staffed project building a Mercurial layer on top of the monorepo VCS that allowed for DVCS-like workflows, such as a local patch queue with multiple dependent changes out for review simultaneously. That little bit of exposure to Mercurial was enough for me to realize that being a DVCS doesn't necessarily require exposure to all the "bare metal" paper cuts that git exposes you to.
If every time the journal / write-ahead log was flushed, the files were rehashed, we wouldn't need index vs non-index so much.
We would use normal commands to sync two work trees one being what we have, and one being what we want to commit.
Instead of .gitignore we simply should have temp files elsewhere.
Basically the file system is a bad abstraction and all VCS is ad-hoc work around it.
There's a dread, a fatigue... I got burned merging (or was it rebasing?) and now I often just copy my folder to make a temp branch.
By the way, how do you extract a file from an old commit without checking out (and crushing your current files..) ? No hassle with the old folder-copy-tech !
For the former, there's git checkout <branch> -- <filepath>, which has been given it's own command as git restore --source <branch> filename.
For the latter, there's git show <ref>:<filepath>, which you then pipe into the file you want to write, like
git show master:src/main.js > temp_main_old.js
Adding HighFlow on top will just add more commands because inevitably there'll be a point where some HighFlow abstraction fails and you have to go to Git anyway to fix it.
Also I can see that HighFlux runs as a daemon. That seems sub-optimal - sucking up my CPU all the time on the off chance I want to code something is not great.
It doesn't seem like HighFlow supports actual remote repositories except GitHub. Which is the entire point of a distributed version control system - to be distributed.
I think HighFlux is designed to solve a very limited subset of Git's usage and so they've stripped out a lot of useful commands they don't use and so they can ship a product.
But in the real world people will need this and their simple vision will crumble back to the complexity of Git (or close).
> I think HighFlux is designed to solve a very limited subset of Git's usage and so they've stripped out a lot of useful commands they don't use and so they can ship a product.
Yes and no. No - once you correlate the user intent with the git commands, you discover that to accomplish one "intent," such as "start working on a feature," - you only need one CLI/UI command: "create WIP". So naturally, many git commands are bundled into one user intent.
Yes - true - we're just starting, so naturally focusing on the most used scenarios, gradually covering more and more cases as we progress. The nice thing is that HighFlux is not only compatible with git but also inter-operable with it, so you can always "go back to git" - until we cover all of the scenarios.
I really don't know why anyone would use these new "easy" commands. They don't feel that much better and their existence irks me because now there's even more ways to do the same thing.
Different isn't always better, but better is always different.
Why? I recently configured my github to use a hidden email address. To this end, it required me to use a github.com email address it generated for my commits. I set it up and started pushing commits, everyone was happy.
Then I went to a different folder that had a separate clone of the same repo, and I forgot I had configured github this way. I made some changes and did the usual commit-and-push but github rejected it. I had used the wrong email. Oops.
But now I had a problem. My local repo had the commit with the wrong email address in place and I didn't know to change it. I couldn't make a new commit with the new email as the old one was still there. I looked up how to revert already committed commits and long story short I did it wrong and deleted all my recent changes.
Next time, if you want to reset the latest commit to an unstaged state:
git reset HEAD~
But regarding "deleting all my recent changes", another command I'd like to introduce you to is; git reflog
It shows you all of your commits that changed the tip (HEAD). Chances are your changes could be found there.I don't blame you for not knowing this. I learned by trial and error and most importantly, good colleagues who showed me the way.
edit: Typo/grammar
Most of these are 'plumbing' commands, not 'porcelain' commands. Perhaps the author should have read the book on the Git website¹, as it explains this.
> Git tracks 4 versions of files, instead of just "my" version and "the team's" version.
This is because it's a distributed version control system, not just a tool to upload files to GitHub.
It seems like the author hasn't even taken the time to understand the basics of Git, and its design goals, before writing this ignorant screed.
_
99.9% of git users use only one remote. Most of them (>85%?) use GitHub. It's like having your car be super complex to drive to work every day, but if you want, it could also dig a hole in the ground. You never use the damn drill, yet it bothers you every day on your way to work ;)
git branch <temporarybranchname>
git checkout <originalbranchname>
git whatevertomfooleryyouwant
And if everything is foobar
git checkout <temporarybranchname>
Or, if you think the liklihood of messing stuff up is higher than the likelihood of success, make your changes to the temporary branch.
Learning what rebase actually did and the difference between reset soft/hard/mixed along with using the reflog to get back to previous states made git a lot more understandable to me.
That said, if you want to see how insanely complex git is, try reading its many man pages.
— Isaac Wolkerstorfer
I use git constantly and hardly ever have problems with it, but only because I use a tiny fraction of it and I religiously follow an exact process every time. I've had people tell me all sorts of reasons why my approach is not good, and they're probably right, but it's really nice to not have to give my VCS very much thought 99% of the time.
Isn’t this one of the main purposes of branching?
Also git is easy to use. You can ignore the non-basic commands as a small team or solo dev, and there are plenty of GUIs to help with UX
Once you realise why git is like that, I haven't found it that bad.
It's no different than someone who has only ever ridden a bicycle asking why a motorbike is so hard to use. Because it does more stuff.
checkout, pull, commit, push and reset if you make a mistake. I'm not including one time commands like clone and init.
tldr: the 'undo' in Tower has been really handy for me over the past few years. Really handy.