"git-eliminate-head eliminates all downstream heads for a few forward-ported non-counted downstream indices, and you must log a few histories and run git-pioneer-object --pose-file instead. [...]"
Thank you for sharing, this made my week.
Git is one of the most amazing, powerful tools ever conceived, with one of the must byzantine and ridiculously designed 'interfaces' ever conceived.
People confuse the raw power of a tech, with how well it can be feasibly used. Sadly, due to the later issues, git will only ever be a shadow of what it could have been.
With all due respect to Linus, who'd be the first to admit he's not very good at UI stuff (I mean command line as well)... it's truly a sad thing.
This is a major 'problem that needs to be solved' I'm interested to see how it could evolve into something 'better'.
A better solution for prose was to always be merging with live multiple collaborator updates. Conflicts are visible in real-time. I can't see something like this would work with code. Hmm interesting... unless we only allow additions and refactorings to working checkpoints.
First - the UI is a mess, and that should have been fixed. It would make a big difference.
Second - is the inherent complexity. That's a good point, but I feel many things could be hidden or obfuscated.
Most poignantly, Git does something that most of us do not need: it was designed to work as a 'completely distributed system', i.e. for open source.
Almost none of us do that. 95% of uses cases related to you and I working collaboratively, on a project together.
The need to have repos which are essentially totally distinct from one another is a huge source of complexity and it simply doesn't need to exist in most cases.
So Git is basically an 'admin level tool' that is commonly used in scenarios for which it wasn't meant to be used, with a confusing interface.
It's costing a lot of time and money and headaches, I do believe someone may come along eventually and fix it.
This thread is essentially evidence of this - see how many people have difficult teaching what should essentially be a simple thing in most cases.
Way too many very smart people still spend too much time clustering around in git.
Nobody is complaining about there being too many features. People are complaining about the arcane incantations that one needs to conjure to call them.
That's just one example, but there definitely are people that think git's too featureful. As for more valid criticisms, I'd agree. I've heard the CLI compared to being in an abusive relationship. All that said, I can't really think of a better way to handle things without losing useful functions. In which case, I don't have any better ideas, and don't really know what I'm criticizing.
but maybe that's due to the low bar that it's being compared to.
> To rev-parse an automatic FLOUNDER_LOG or diff the working subtrees, use the command git-link-submodule --retrieve-wrestle-change.
I often overlook this detail when trying to hulk smash some broken change I've made upstream (what the manual entry correctly refers to as RIP_OTHER_TIP).
"To parse a staged SKIRT_SUBTREE and blame the working histories, use the command git-purchase-pack --snuggle-muster-branch, as after reapplying subtrees..."
Content Security Policy: The page’s settings blocked the loading of a resource at self (“script-src”).
The most effective work flow I have found so far, is teaching only status/clone/pull/add/commit/push. Show them explicitly what happens normally, what happens when two changes conflict, and how to resolve merge conflicts. Using git on the command line only.
Then, have the students use git for a big-ish multi-student project. They will figure out the workflow themselves. After that project, once they understand the basics, you can talk about branches, debasing, the log and reflog, pull requests, and all the rest. Don't introduce graphical front ends before this point.
This method works well. It takes about one hour of teaching, and five weeks of active use afterwards. Git is a total pain to learn, and can only be understood by actively using it. I often get very positive feedback for having taught git.
I have gone through a few iterations with this topic, and have found that stripping down the initial instructions to an absolute minimum works best. All those fancy box diagrams are actively harmful to beginners.
Also "git log".
"F*ck this shit, make your own UI on top if you want to use this tool!"
I don't think Torvalds has a proper excuse for the pain and suffering he's inflicted on millions of developers worldwide :(
(To the people going: "Oh, it's Open Source!". Sure, so are Mercurial, Fossil, etc.)
Another factor is that git was always FAST, and the most common operations (init, log, status, commit, checkout, push, pull) are not that complicated as people make them to be, so you can very easily start to use it for new local projects, and continue without installing additional plugins, unlike mercurial ... And at some point, when you wanted a colaboration hub or just a public remote repo, you just pushed your code to github.
Actually this is exactly what happened back then, which is why many people used https://en.wikipedia.org/wiki/Cogito_(software) as a frontend to git in the early days. That said, I personally find current git UX absolutely fine and I can't imagine being effective without having all those commands like git reset --whatever -p and git rebase --interactive.
Who are you exactly to judge people like that, oh failed incarnation of a tibetan Lama ???
He does not need an excuse to make a tool that has proven very useful to many (including me). In fact, I am grateful, that he chose to make it and publish it.
Certain tools are organized by what code goes together rather than by what user functions make sense to go together. It's part of what makes it confusing.
git config --global alias.lg "log --color --graph --oneline --decorate"
Of course four will work, it just adds more indentation.
SourceTree tends to treat commits with multiple ancestry in a very weird way that has led to difficulty on multiple occasions, where people think changes 'went missing' because SourceTree decided the other ancestor wasn't important enough to show.
Also `git whatchanged` is a super helpful command to see just the list of files that changed in each commit
If you're interested, here's my .gitconfig, including all of my aliases: https://gitlab.com/lyndsysimon/dotfiles/blob/master/git/gitc...
has nice color coding around the date, person committing, commit hash, and message.
If I had trouble with understanding the reason behind add->commit->push workflow, I would definitely have no idea what this article talks about when it says things like "merge, rebase, diamond shape". The flow chart looks almost exactly the same for "pull" and "pull --rebase". The only difference between the charts is the wording which has no meaning at all for a newbie.
"pull" and "pull --rebase" can cause two kind of conflicts:
1. Merge or rebase conflict inside the repository.
2. The would-be merged or rebased HEAD conflicting with the dirty working directory.
The article demonstrates the latter and it's the less important one as it's avoidable by pulling from a clean working directory or pulling a non-HEAD branch.
How to write a Good Commit Message (https://chris.beams.io/posts/git-commit/).
I've tried a similar approach years ago for teaching and failed spectacularly. Eventually, my peers became comfortable when they got used to the Github Desktop Client. They compared the buttons they click with my terminal commands. We also compared our graph views on Github website to visualize the logic.
It's been years and still none of them used rebase even a single time. A sad story in my teaching non-career. :(
For me, command line is freedom. GUIs are very limited.
Don't give up! For my humble experience:
- Try to know your peers, how they work, what difficulties they face when using command line, ...
- "I'm lost" > "git status"
- "How did we solve... ? > "git log"
- "This command is difficult to remember." or "This command makes no sense, I prefer this another name for that action" > "git alias"
* Git From the Bottom Up: https://jwiegley.github.io/git-from-the-bottom-up/ (PDF: http://ftp.newartisans.com/pub/git.from.bottom.up.pdf) (See also: "Linus Torvalds' greatest invention": http://perl.plover.com/yak/git/) Once your mental model matches the program, you'll be able to understand everything, hack your own solutions if necessary, etc.
* Learn Git Branching: https://learngitbranching.js.org -- in fact I think this should be the UI for Git; wish someone would make that happen (i.e., so that you can point it to any Git repo and get that sort of visualization for it).
Similar to magit - Sublime Text also has SublimeGit, not as fast as SublimeMerge.
Visual Studio Code built in git functionality is also nice.
And then git fetch/push/pull are mostly about copying parts of that graph from one place to another.
After that, it's mostly a question of what workflow you want and that becomes much more than a git question because git works for a variety of workflows, and many of the features of git are really only relevant for certain flows.
I recommend GitX (FOSS, Mac only, a little buggy but has the most logical UI and let's you easily amend commits), SourceTree (free, quite slow, Windows/Mac), Tower (paid, cross platform) or SublimeMerge (paid, easily the fastest, cross platform).
That taught me in a few weeks of usage more git 102 and 201 type functionality than a year of using only the basics did.
A couple months later, and a bit more experience with how emacs structures things, and I've returned to Magit and _love_ it. It just feels natural to hop around in for standard tasks. Certainly a good replacement for other porcelain UIs I'd normally use.
I'd add oh-crap-I-screwed-up-so-let's-clone-the-repo-and-start-over to the list.
I have no idea why anyone would want to go back to SVN. If you don't want to use all the features, I understand; by all means, continue to only ever branch -> commit -> push -> create pull request. There's no need to subject the whole team to version control that doesn't work. That's what sold me on git; it's the only version control system that never failed at it's job of letting me track my changes. It doesn't break it's promise to always be there for me.
SVN, centralized systems, and even mercurial to some extent, prevent users from tracking their changes. This leads to questionable workflows (lots of copying directories to "save things"), or even worse, developers just don't track their changes at times. It sounds weird that I have to say this, but I feel that version control systems should be available to track changes 100% of the time. It seems like many of the people who dislike git, don't see the value in this, which I find absolutely baffling. Git means never being scared to create a commit.
False. Stop spreading misinformation about Mercurial.
"Git means never being scared to create a commit."
This is indeed one of the biggest benefits of DVCS tools, including git and mercurial.
I'm unaware of anything within base Mercurial that lets me do what I can do with git. Maybe the answer is to use the extensions, however that's a bit unsettling when some of them are being depreciated (eg. hg queues). Often times I found myself cloning and maintaining multiple directories for something that was better off as one thing. This led to reluctance to track changes, which is clearly evil. I guess I must have been doing something wrong, but I've heard similar feedback from others regarding Mercurial. I loved using hg and would have no problem using it (it was my first); I just prefer git now.
Once you have the better understanding of the graph, it's hard to find resources on how to improve from there; most resources focus on beginner stuff, or function more as a technical reference without really talking about use-cases. I've found following Mark Dominus' blog for his posts about Git to be the single best thing to "level up" my Git usage once already being at a high-level.
: At the time, I had to pay money for the eBook, now they have the whole thing on GitHub: https://github.com/pluralsight/git-internals-pdf
- Commit a "secret" and involve it in other branches, commits, merges, etc. Then remove the secret so that nobody can ever learn it from the repo.
- Clone a repo from another local repo and then rewrite history with rebase and revert. Then commit different work in each repo. What's the least painful way to get them "compatible" without losing any work?
When new colleagues joined our firm and hadn't yet learned Git, the problems were always the same: uncertainty. They didn't know which Git operations were safe, and they didn't understand how to perform seemingly risky maneuvers with zero risk. They're used to even more dangerous tools that can wipe your work in a second - and, to be fair, Git can as well. The difference is that once you understand Git, you never have to worry about losing work.
So the way I would teach Git is to honestly start with the graph. Show it in action with pictures. Show how to always keep references to commits around to ensure work sticks around. Show how branching and stashing work, let them be confident that the tool will keep everything right where you left it.
_Then_, once they're confident in the basics, weave in the remote repositories.
Personally, I think this should be coupled with teaching `git reflog` as the universal undo (as long as they don't `gc`).
I understand your second point, but I have a hard time understanding the difficulty with this part. Why is it hard for people to understand the idea of staging?
You put things in a box one at a time before closing the box. Does it require more explanation than that? What do people find difficult about it?
People often then learn that there is a local file and some remote file: they can cope with a save -> upload workflow. Lots of traditional VCS turn this into a save -> commit workflow.
Git adds two stages to this that people can't see the need for without understanding the internals: an extra step between save and commit, and an extra step after commit.
(The discussion reminds me of all those people who think that if they just start by talking about monads then people will find Haskell easy and natural...)
1. Is my document saved?
2. Are the changes staged?
3. Are the changed committed?
4. Are the changes pushed to my fork on e.g. github?
5. Are the changes merged into the upstream repository on e.g. github?
However, I find the occasions for using the staging area in practice are few and far between, for the simple reason that I can't test and execute the code that's in the staging area without also having the code from the working directory also be there. It feels like after having partially staged some of my working directory, it would be a blind commit with no guarantee that things are working.
Very rare is the situation that I can break out a list of files over here that are for feature A and some over there for feature B, and never the two shall interact.
I think this is probably what most struggle with regarding the staging area, without being able to articulate it.
I do not see why a source control system should make it easier to make a commit that hasn’t ever existed on disk and thus cannot have been tested.
I think the better model would be to stash your changes and have an diff editor between the on-disk working copy and the stashed version that allows you to commit a set of changes as several smaller, more coherent commits.
That wouldn’t guarantee that each of those intermediate commits gets tested or even built, but it would guarantee that each smaller commit is in the on-disk copy at some time.
Not necessarily. One nice option that the git rebase command has is --exec (which can be specified multiple times). So you can run a rebase and have git execute a command (like running a test suite) for each commit in the branch. If any commit files, the rebase process will stop and let you amend the commit to fix the issue.
> or you have to do extra work (stash changes, test, restore stash) to do that.
I've found that it's easier to write and locally test a given feature and them incrementally stage parts of it and create commits before pushing the code up for review. To me, that's easier than just making a large commit and then trying to split it out into a better set of commits after the fact.
For example, I may write a new method and then call it several places in the code. So my first commit would be to add the new method along with its unit tests and my second commit would be to add calls to it in the code base and update the associated integration tests (if necessary).
Almost. Most often it's:
- Working on solving problem A
- Notice problem B
- Start to solve problem B
- Notice I'm getting distracted from A, and return to finish it.
- Want to commit my fix for A, but don't want to lose or forget the partial work on B.
Two different approaches I might take in this situation, depending on whether B is related to A.
1. If they are related (eg, B depends on A), use `add --patch` to commit A, then finish and commit B.
2. If unrelated, use `git stash --patch` to stash B, then commit A, then switch to a different branch to finish B.
Honestly, I see the point of both stash and staging, but not both together. Too many tools for the same job. On my long list of projects to do is a git porcelain that combines some of these concepts (eg, stash and working directory which would be tied to a branch):
- Each branch would have a single stash.
- When you check out a new branch, all uncommitted changes are automatically stashed.
- If the branch you're switching to has anything stashed, that stash gets popped.
- Any current workflow that involves stashing can be replicated by using a branch instead of a stash.
This way, branches can be thought of as "state of the working directory", which is more intuitive with the branching tree model, imo; commits are a snapshot of the repo at that point in time; and the staging area is just a way to choose what should be included in those commits.
Git’s workflow wouldn’t even be sane without the staging area. This is what allows you to fix mistakes and make your work presentable for remotes.
I did exactly the same diff/tidy/diff workflow when I used p4 and svn, neither of which make a distinction between "working directory" and "staging area".
P4 and svn don’t have a strict commit parentage, which is why you can push commits in those systems in any order. Git’s strict concept of parentage is what makes the staging area so important for keeping your workflow similar to p4 & svn Workflows. Without a staging area, you’d either have to always fix mistakes with new commits, which is bad, or rewrite already pushed history, which is worse.
The terminology is a bit different - unless configured with mandatory locking (essential for some workflows) you don't have to open for edit. You just edit stuff and it goes in the "default changelist", roughly equivalent to automatic staging.
> Without a staging area, you’d either have to always fix mistakes with new commits
Mistakes at what point? In the normal svn workflow you can review with svn diff, then when you're happy do svn commit; it's just that there's no local place you're committing to. In both cases there's a critical point, either "svn commit" or "git push".
I’d guess you’re learning toward talking about svn, which I don’t remember very well, and I am leaning towward talking about p4, which always does mandatory locking.
You’re right the terminology is different between these different systems, I’m just pointing out that the git staging area has what you can think of as some equivalences in the other systems. Or, you can think of it as tradeoffs. Either way, the git staging area is something that helps you pretend like you’re using svn or p4 in the sense that it helps support editing multiple changes at the same time before pushing them to a server.
> Mistakes at what point?
With git I’m referring to mistakes between commit and push. But there’s a philosophical difference here that I glossed over. With git it’s easier to commit early and often than it is with svn or p4. With svn & p4 it’s easier to lose your work because version control doesn’t know anything about it before you push. If I make micro-commits, which I want and I like, then I put more “mistakes” along the way into my local history, and I can use the staging area to clean everything up before I push. With svn & p4, you make those mistakes and do the cleanup without ever telling the version control, and you run a greater risk of losing that work while you do the cleanup.
At work I’ll hit the squash option on gitlabs merge request which moots all local machinations.
It's also possible to do this without the stash command, by making both commits right away, and testing them later. However, that would involve rebasing(?) your second commit on top of any changes you end up making to your first commit, so using the stash makes more sense to me personally.
The git stash man page talks about this: https://git-scm.com/docs/git-stash
“If you mistakenly drop or clear stash entries, they cannot be recovered through the normal safety mechanisms.”
One of the best things about git is how big the safety net is, as long as you tell git about your changes. Almost any mistake can be fixed, so why use features that aren’t sitting over the safety net?
You're adding a feature to your proggie. That involves modifying the main bits to add the feature and, say, adding a couple of interfaces to internal library modules.
Split out the changes to the library modules into separate commits---it's safe because nothing uses them, they're logically separate from the feature changes (although they don't appear to have a justification without the feature), the log will be marginally cleaner, and git bisect will have more granularity.
Your example is an implementation of the box-putting algorithm, but it doesn't need to be mirrored in the put-box CLI.
put-close-box file1 file2
put-box file1 file2
Anyway, `git commit file1 file2` by itself is most of the way to being the put-close-box function you want; it just doesn't work for adding/deleting files from the repo. Seems like they could make a lot of people happy by closing that gap and letting `git add` be an intermediate-level feature.
But the vast majority do, or at best become perpetual intermediates (https://blog.codinghorror.com/defending-perpetual-intermedia...).
99% of developers out there didn't need a power tool for source control (source control is already quite a power tool many devs can barely handle, even in SVN form...), yet here we are: Git is imposed everywhere, with its horrible UX.
Many beginners will start by always doing "git commit -a" and that's fine, as long as they know there's an alternative once they need it.
Surely, most of the time when you go to commit, it's all the files you've changed?
EDIT: Now that I think about it, I also have several repos where I have changes that I never intend to ever commit them, because they are development conveniences for me personally.
I'm a JS dev mainly working in React on a web app with a backend team using PHP. Often I'll be working on a branch with maybe 2 or 3 people and I often end up working on a few things at a time. Say I'm working on a feature, and I notice some bug I'll fix that and then get on with my feature. Once I go to commit I pretty much always do a 'git add . -p' and I very rarely want to add all the files I've worked on!
Even things like switching a config file to use a service like apiary where I don't want to commit my change to the config to use apiary.. Or change to my webpack config for testing, etc.
I've used Perforce, SVN and Git and the whole 'staging' area thing always felt very natural to me. Here are the files you've edited, which ones want to be commited? It gives me a second chance to go through and check everything before I've commited, and often that stops me leaving in any odd comments or debug code.
What is the usecase where one needs to remember that selection for more than just a few minutes?
In Mercurial, I much prefer to just make it an actual commit in the draft phase (the default phase) and just keep rewriting that commit. Mercurial provides tools for both selectively adding and removing hunks from a commit (both `hg amend` and `hg uncommit` accept --interactive for hunk selection). If you're extra paranoid, you can make it a commit in the secret phase so it's not shared prematurely by accident.
It's pretty much functionally equivalent and doesn't require an extra location in which your code can be. It's either in your working directory or in a commit.
A bonus of this approach is that now you have a meta-history, hidden by default, of what you've "staged" and "unstaged". It's kind of like a reflog but with, in my opinion, a better UI. And of course, the index/cache/staging area in git doesn't use refs, so there's no reflog there.
git commit --verbose --patch
No, not how to teach Git.
Open source just can't do good user interfaces. The result is almost always a zillion features in search of an architecture.
Blender managed to almost dig itself out of that hole, but it took over a decade. Gimp is still down in the pit.
a) VirtualBox is an oracle product. That by itself should be telling.
b) High sierra is unsupported as a Guest OS in VirtualBox. You do know what that means, right?
c) You seriously complain about the darth of open source virtualization for an OS, which disallows virtualization on anything but apple hardware? ...really?
If you want good open source virtualization you'll want to use Qemu/KVM. Which obviously doesn't support any apple OS either, because they're not allowed to virtualize it. Take that up with Apple, not open source
Putting aside the fact that this isn't true, and that there are quite a few quality open source apps on macOS, it's pretty clear why paid products have higher quality: the bar for people to buy them is much higher, so they generally need to be at least somewhat decent for people to consider paying for them.
So, virtualization is technically only allowed if you're running your apple hardware with anything besides Mac OS.
But apple isn't enforcing that limitation, as products like VMware fusion on Mac OS are (at least as far as I can tell) officially sanctioned.
If you obtained a license for the Apple Software from the Mac App Store or through an automatic download, then subject to the terms and conditions of this License and as permitted by the Services and Content Usage Rules set forth in the Apple Media Services Terms and Conditions (https://www.apple.com/legal/internet-services/itunes/) (“Usage Rules”), you are granted a limited, non-transferable, non-exclusive license:
(i) to download, install, use and run for personal, non-commercial use, one (1) copy of the Apple Software directly on each Apple-branded computer running macOS High Sierra, macOS Sierra, OS X El Capitan, OS X Yosemite, OS X Mavericks, OS X Mountain Lion or OS X Lion (“Mac Computer”) that you own or control;
(ii) If you are a commercial enterprise or educational institution, to download, install, use and run one (1) copy of the Apple Software for use either: (a) by a single individual on each of the Mac Computer(s) that you own or control, or (b) by multiple individuals on a single shared Mac Computer that you own or control. For example, a single employee may use the Apple Software on both the employee’s desktop Mac Computer and laptop Mac Computer, or multiple students may serially use the Apple Software on a single Mac Computer located at a resource center or library; and
(iii) to install, use and run up to two (2) additional copies or instances of the Apple Software within virtual operating system environments on each Mac Computer you own or control that is already running the Apple Software, for purposes of: (a) software development; (b) testing during software development; (c) using macOS Server; or (d) personal, non-commercial use.
There are people who love illustrated explanation and for those these are perfect. This is just meant as a template which others can use to build the illustrated material and in no way a comprehensive git tutorial.
- show what happens as you add commits to a branch
- show that branches are just pointers to commits
- show what creating new branches looks like, i.e. creating a new pointer
- show what merging looks like (a new merge commit is added, or else fast-forward merge and that the branch pointer just moves)
- show what happens if you don't rebase (i.e. "ugly" non-linear graph) ... then teach what rebasing does (i.e. creates new nodes and moves the pointer)
I found that building up from the ground up and illustrating graphs allowed people to conceptualize things much better. There was still some confusion once merging was introduced (what happens to those earlier commits? do we need them?) and mostly because people hadn't thought of the graph before.
Git is one of those tools where you can totally do your job just by knowing the basic commands but not really know what is happening under the surface, which I think is a testament to the tool. But, that leads people to conceptualize their own idea of what is going on... and getting it wrong and being confused when they want to do something outside of their basic toolset.
Git's mental model is basically:
> Ok, what if we took our SVN repository and the first thing we did was check in an SVN repository to that. So now you check out the repository, and you get a complete local repository that you can do anything you want with!
> So Pull/Push are the terms we use for the check out and commit of your local repository to the remote repository, and then Checkout/Commit works from your local repository just like you're used to with SVN.
And the real magic is what they did by building a system on top of this model to let you merge changes all the way up while looking at the code like you'd expect you'd need to.
The problem is that git's toolchain still feels arcane to use, and it requires that you have good working knowledge of the underlying models. It's confusing enough that you can't function unless you have that because you don't know where you are or where you're going. It's a fantastic tool, but it's like driving a car with two steering wheels, two gear shifters, and six pedals. Then you say to yourself, "How do I get to the market, buy some milk, and come right home?" and your brain starts to melt a little bit.
You shouldn't need to know the nitty gritty of how git works internally just to get it to work right any more than you should need to know how a disk works in order use a file system, but over and over we keep seeing that knowing that is really the only way to use the tool correctly and that it takes quite awhile for people to get.
There was still obviously the issue of memorizing the commands, but at least I knew what the commands were doing on a deeper level.
Substitute C, Java, Python, etc for git. You can probably do something with those languages, but you aren't going to get very far without reading some sort of documentation.
But git isn't complicated. Git is a handful of simple ideas composed in interesting ways. It looks complicated because there's a lot of porcelain commands with a lot of options, but all of them are just manipulating the same simple internals which, once understood, are clear and intuitive.
On the other hand, I've used ClearCase.
(Do not use ClearCase.)
Thing is, dealing with git feels like being in the early 2000's using Clearcase views.
As for the teaching part, I have found the best results by having you and the learner actually "working" on the project at the same time on your own machines both pushing to a centralized server. It becomes too easy to go over all the commands and feel like you understand it. Most of the scary parts of git are used when its multiple developers on the same project. And oddly enough, having the learner do both Developer A and Developer B's tasks don't seem to work as well as having the learner just do Developer B while I do Developer A. Trying to explain to someone when to use merge, when to rebase, and when to use cherry-picking to get the code I just pushed into their current working branch can be done so much easier when its hands on AND knowing exactly who is doing what steps.
To understand the data structures interactively, use "git cat-file -p HEAD" and continue drilling down to an individual file in a subdirectory with "git cat-file -p OBJECTHASH"
Git fails majorly in this regard.
"Git sucks, the UX is atrocious, I don't want to spend half my life learning a tool that shouldn't even need that much hand holding."
It may seem paradoxical at first to you, but is true (as are many things in this profession). Another paradoxical advice like that, is to learn vim, or emacs, but I digress.
Git does not suck - as any other tool it, it just has strenghts and weaknesses (for example working with very large binary assets is its main weakness).
The UX of most common git CLI operations is clean actually, as they are fast, and you do not need many arcane options (although they are there, and are documented well, for people who read...).
If you screw up something, you just use the reflog to fix the state of your repo in most cases. Even if you can not (or do not want to), the troubleshooting is still easy - you can always do a fresh clone from your remote repository in a new folder and copy what you want there.
Regarding Git, Git does suck. It does the job Linus designed it to do, but that job is not most software engineers across the world need it to do.
In smaller or in corporate shops, Subversion was almost adequate and several bad implementation details, mostly related to branching, led to its demise. So that world needed Subversion++, not Git.
In the FAANG world, there's basically no company that uses Git as-is. It's strength/weaknesses aka tradeoffs aren't good enough for them.
Git won because tech is a popularity contest and people in our domain like to do a lot of virtue signalling ("this tool is hard to use, I use it, so I'm special/cool").
>> It does the job Linus designed it to do, but that job is not most software engineers across the world need it to do.
Speak for yourself, you are not most software engineeers.
>>In smaller or in corporate shops, Subversion was almost adequate ...
I have administered SVN profesionally for several years (2005-2007), and was paid to unfuck screwups made by other developers using it (which many times involved restoring from incremental hourly backups done on the SVN server side). Dealing and helping others with their git problems is many times easier.
The FAANG world (which I had to google just now) I imagine has unique requirements (many teams that must coordinate, super gigantic legacy source code base), and the resources to do whatever they want (money, humans to develop and maintain tools and do research). For them, the integration pain from managing multiple smaller repos may be significant. Outside this world however, teams are more independant and the source code size is much much smaller (even for legacy projects).
>> Git won because tech is a popularity contest
You have a point here, but this factor (and network effects in general) is just inertia, and does not explain why git won, given that for example SVN or Perforce had such a head start (in tooling, and in mindshare), and there were other distributed contenders like mercurial and darcs and BitKeeper developed at aproximately the same time, and even earlier. It won in my opinion because it was simply superior tech - faster, good enough and very very easy to get started.
(edited to clean up formatting)
What do you think is wrong about it? Or have you only "read a ton" but never used it for a while? In the latter case, I suggest you start with the things I mentioned above, and make good use of "git reflog" as suggested by somebody else. If you know git reflog, "delete tree and clone a fresh copy" is not a thing anymore.
> In the FAANG world, there's basically no company that uses Git as-is. It's strength/weaknesses aka tradeoffs aren't good enough for them.
Do they use svn then?
And how many people do that? Not that many. This angle is a bit like the guy who said that he doesn't want Unix file names to be UTF-8 text-only, because he crafted a sort of relational database on top of a Unix FS and by having file names be just text he couldn't do some super niche trickery. I think it was in response to this article: https://dwheeler.com/essays/fixing-unix-linux-filenames.html
> If svn is enough for you, that's fine.
It is, but every job these days forces you to use git. And most places I've worked at, git is used as a glorified SVN where people just have a 2-step commit to a remote server.
I regularly fix my commits, (just like I edit most comments on hn within a few minutes after sending them). And sometimes I take back commits even from the server (working in small teams).
Locally, I regularly switch to older commits and branches to try things out. In svn all this requires a network connection and it is quite costly. Which means you do a hell of a lot less of it. And I would assume it shows in software quality.
Man, how I used to freak out regularly waiting for a stupid svn diff or svn log to finish. These operations are the bread and butter of version control, and they are instantaneous in git.
Or, aren't you regularly blocked from doing quick fixes using svn for problems that you saw, but couldn't fix them because you had a different pending commit? I have that often when working with svn (admittedly I don't know svn very well, but I'm sure it is a real blocker in many situations). Situations like these are easy in git.
And how idiotic, after all, is it that we have to setup a SERVER to keep a simple log of changes to a few files? I have so many small ephemeral projects that I simply put in my laptop's home directory. There is no point in maintaining server repositories for those. Git is simply a tool that lets you do that. It lets you do bookkeeping of your data. It's a tool. While svn feels like an inflexible process. (yes, svn has the file:// protocol, but you still have to setup a separate repository, right?)
In a sense, git is the sqlite of version control. You are really missing out.
> It is, but every job these days forces you to use git.
Here in Germany, svn seems to be the norm still in the engineering domain. But I figure the situation is quite different for web shops.
> And most places I've worked at, git is used as a glorified SVN where people just have a 2-step commit to a remote server.
That's my experience as well. When it's about communicating changes most setups will be centralized just like a regular svn setup. It's a fine approach for small teams. But with git you still have the huge advantage of being independent of the server. And you can easily fix problems that are already committed to the server.
However, what you do need to understand is the model that git uses, which is extremely simple.
Git provides you a way to store snapshots of data into an on-disk graph data structure* that you can sync to and from remote repositories. You also get refs to store symbolic references to the snapshots in the data structure, and you can sync those too.
That's pretty much my mental model of git in its entirety, and it allows me to merge, branch, rebase and perform all kinds of commit surgery with ease, because I can always tell what effect an operation is going to have on my data structure (and even if I'm wrong, I can't lose data)
I seriously can't see how it could get any simpler.
(*) a git repository can actually contain several separate graph data structures, but that's usually not what you want...
However, this only works with people who can make the mental leap to be able to deduce knowledge of what should be from knowledge about what is. In the end, I concluded it's a bit like teaching cooking. There are those folks who need to be taught about full recipes and those who need to be taught about resources and corresponding steps.
I have not yet seen a working approach to make both of these fractions happy, unfortunately.
There is a point, where you go from memorization (add, push, commit) to deduction (graph, objects and refs) but when this point is reached, depends on many individual factors.
Using a git GUI works quite well for people inexperienced with git.
GUI integrations have some advantages but the knowledge is not transferrable. Different GUIs work differently but the commands stay the same. I think both can complement each other. I use Pycharm a lot and it is a lot easier to see diffs or file history there. I think the same can be done with cmd as well but I don’t think I ever bothered to learn advanced commands.
I would posit the ed text editor for comparison. Why bother with a graphical text editor (including terminal editors like Vi and Emacs)? After all, you can look at the context surrounding lines you wish to edit by entering the appropriate ed commands.
I think it comes down to developers being so used to working with command line tools that they don't give GUIs a proper chance - ironically the exact objection they have with less experienced users not using the command line.
1. Most GUI's give you an overview of the changes before committing.
2. Most GUI's let you commit and push in one go, and also show unstaged changes so you don't forget to add/commit/push anything.
3. A good git GUI is explorative. Newbies just remember the icons to click at first, and they learn more by exploring menus and reading messages.
4. Commit histories are easier to view and filter.
5. Exotic steps are easier to do, since you don't have to remember commands you barely use.
6. Adding remotes is a piece of cake.
> and if I mess up, quitely crawl back to the peaceful place.
While I understand why folks may want a GUI for git, I am continually amazed that there hasn't been an effort to "refactor" git commands so they're more consistent, easier to remember and easier to discover. It's a miracle that git has taken root so strongly, given it's shitty user experience.
I've been using git for years, and STILL, I need my cheatsheets and google far more than I would ever admit in person. Anything that's outside of heavily practiced workflow-- and I'm in a world of confusion.
I agree, and I wish there was a really good git GUI that either abstracted git nicely, or was as powerful as the CLI, or both. I’ve tried many of them, in production, and there aren’t any that give you a UI for everything git can do.
The problem I’ve noticed is that people raised on the GUI often don’t understand how to get out of trouble once they have a serious problem. Also the GUI tends to be a crutch that prevents them from learning the CLI well.
Git is natively a CLI and it really shows once you know both. Git’s CLI interface is awkward and hard to learn, and all the GUIs for git are somewhat awkward, both due to git being awkward, and also because trying to fit UI workflow onto CLI commands introduces awkwardness. All git GUIs are incomplete interfaces to git, there are none that give you access to all of git... specifically things like finding lost data and managing repos is something you’ll need to drop to the CLI for.
For example, I've never had any problems with Mercurial. Everything just works there and it is intuitive. You can never lose data there, and it has extremely sensible defaults.
From UI/UX point of view, developers are users as well, but many seem to think developers should put up with bad interfaces.
Yes, once electric cars (with superior traction and brake control) take over automatic gearboxes (actually electrics don't even have gearboxes) will be the norm, but as long as there are engines driven on dinosaur fuel there will be a need for manual gearboxes. Which is why you should learn how to drive one. Once you're able to do that, driving an automatic is trivial, which was the point I was trying to illustrate.
I’ll answer that for you. It’s insightful.
In the U.S. today, less than 2% of new cars sold are manual now. Automatic gearboxes are well beyond the norm already.
I didn’t understand why you said there will always need to be manuals for vehicles that run on gas... what do you mean?
At that percentage, the U.S. is a huge outlier however, and accounts for quite some chunk of of worldwide automatic gearbox equipped vehicle production on it's own.
The automatic gearbox remains the less popular option worldwide , though as you can see they are more popular than they were before.
At some point it's just Stockholm syndrome (we can only afford manual, everyone has it, so let's at least pretend it's cool!).
After all, as GC fan, it does not make much sense to malloc()/free() my gearbox. :)
The point being that what is right to learn today won't stay like that forever.
Only people that maintain old timers still know how to use a motor starter.
The last thing you want to do is turn them off entirely, or gatekeep the profession to exclude people who aren't good at reading dense documentation.
The best way to teach git is to get them comfortable with "Add, Commit, and Push" and then explain what's happening at each stage.
Maybe if somebody has already mastered subversion then git will confuse them a lot, but I'm not convinced even that is necessarily true. Regardless, it seems clear to me that novice users shouldn't be told that git is complicated.
And another great bit: always do `git commit -v` for verbose commit edits. Read your diffs before you commit them.
Would it have killed Jonas to include a screenshot in the README?
I'm not going to install something just because someone says it's good. I have to go multiple links deep to get taken to a Flickr gallery, and even then I'm not sure what is so good about it: https://www.flickr.com/photos/jonasfonseca/sets/721576144707...
1. I want a Git log viewer right in my terminal, that gives me most of the benefits of visualizing a Git log like a "real" GUI.
2. Fast startup. I work in dozens of Git repositories a day, many submodules, etc. To visualize these effectively, I want to type a few characters in my terminal and see the Git history in a digestible way.
3. This essentially `git log --graph --pretty` with the ability to deep-dive into a single commit view of `git log -p` with nothing more than a stroke of the return key. To exit, I hit ESC.
4. Vim-like bindings in a Git viewer. Every visual app that I use daily in my terminal has "roughly Vim" bindings, from Emacs (https://github.com/emacs-evil/evil) to Zsh (bindkey -v) to Tig.
5. This is just as fast to start as `git log --graph --oneline`, but I get a fully interactive view of a Git Repo history. For example, the Linux source .
Perhaps I should compile my thoughts and send some README updates and screenshots to help the project.
Reading this article, it occurs to me how useful the idea of a "staging area" would be to helping them understand. I don't think of it that way myself when I'm working with it (I suppose I do, but not in those precise terms). But looking back, that's what was tripping them up. If you're just talking about local and remote repositories, you're not really giving them the right idea of the workflow.
The specific points that make it great for such teaching:
1. pretty graph
2. hovering over actions such as Commit / Merge / Rebase / Push shows what would happen to the graph if you do it.
3. you can manually "Move" local & remote branches anywhere you want! This is mildly risky as a habit, but much clearer to explain than fast-forward and push, especially with multiple remotes.
4. automatic fetch that works pretty well (though explicit fetch UI with multiple remotes is clunky). For people scared of merging and conflicts, it's liberating to teach "fetch is always safe" and "local commit is always safe", and that you can fast-forward or merge/rebase separate step.
Then you could learn more easily via exploration and experimentation.
And I do mean just one command to undo all the things, I know that you can undo a lot of things in git but each command is different, and I know that undoing pushes is hard.
(Addresses some of the points raised in this article.)
Let's say you were commissioned to create a landscape painting. It'll be a big payday if you get it right and its due in 30 days.
Because you know you can make mistakes, you make a photo copy of your work every day and make a stack of them neatly on your desk. This photo copier is really high quality as copies are made at the molecular level.
On day 16, you find yourself working on the mountains in the picture. You sneeze and Oh no! You got paint all over your work. But since you have your copy pile, you just make another copy of day 15 and keep going.
But lets say you think its a lot and want a friend to work on the painting too. Just allow her to copy your latest photocopy and you both are off to the races!
Git seems complex but when you bring it down to a practical, non technical level, beginners pick it up faster :)
In class I'd stand on my right side, so students see me on the left (people are more used to left to right motions because of reading).
I'd demarcate the working directory, staging area and local repository non-verbally as 3 different spaces. My most right space (the student's left) was the working directory, my most right space (the student's right) was the local repository.
Everytime I'd make a transition from one space to another through add or commit, I'd make a hand gesture when I'd say "add" or "commit".
In order to add some humor (humor is rememerability) with push I'd point upwards to the ceiling as if I were looking to God. I'm not religious, but people got the reference and they all left out loud.
The way to teach these tools is to make them primary citizens in your company culture. Emphasize that, without a strong grasp on a variety of important tools, devs will be unable to perform at or above the bar. Don't promote anyone to "senior" engineer who can't easily show the benefits of these tools while a junior engineer pairs with them.
Otherwise, developers will teach themselves the absolute bare minimum necessary to get their jobs done and go home. The quality of the training materials is of minimal importance. I learned git because I wanted to be better at it.
> how to show the changes of a file in the staging area: git diff --staged
Ok, but this shows the diff against what: the file in the working directory, the file in the local repo, or the file in the remote repo?
Also, it does not show a particular file, but all the changes in the staging area. To show only one file have to do `git diff --staged -- src/myfile.c`
There. I never needed more in a number of companies.
[Yes, somewhat tongue-in-cheek and of course limited to people who use Windows and Visual Studio, but I have discovered that's a significant number.]
Learning the functionality of git can really help you out. For example, I almost always use the `-p` flag (particularly `git add -p` which gives me a chance to manually see every change I've made, often I'll find some junk that I may have left somewhere else. Also being familiar with how to rebase series of commits onto and off of other branches can be a huge time saver.
It also feels like a clunkier workflow than just using git from the command line. It's probably easier to get started that way, but learning the basics of git from the command line isn't too hard.
My biggest issues with git were when you were working in projects that had other usage patterns. It's a bit like C++, apparently everyone uses different subsets and strategies.
Uh, yeah. You don't add random temporary files (notes, temporary testing data, the florist's phone number that you'll need after the meeting you're already late for) to your projects?
What I do: I use GitHub desktop to get everything configured, then use the PowerShell command line to do all my work. Merge conflicts are fixed with VS Code.
Does anyone have a good analogy for this? I think they understood for the most part, but explaining things better is something I have been really trying to improve on in the workplace lately.
(Sorry for mobile link, I'm on my phone RN)