I feel like a much better metaphor is the difference between understanding that turning the steering wheel turns the car and understanding that turning the steering wheel turns the front wheels. You can drive a car without knowing that, but at some point you will find that not knowing that prevents you from having an intuitive grasp of things like parallel parking.
In software engineering, an even more apt analogy is understanding how compilers/interpreters work. You can do a lot of programming treating those as black boxes that make your program run, but eventually you have to have the deeper understanding.
It especially happens after a student has just begun to understand that they can only move in some directions relative to the wind, and they feel stuck with the boat pointed straight into the wind. You have to move to change your heading, and you have to change your heading to move? The first reaction is to feel like the rudder is broken.
Ways to make this faster include pushing the main sail on a small boat out to the "wrong" side, tightening the front sail on the "wrong" side of a larger boat, and positioning the rudder only a little off center so that the slowly moving water relative to the boat is less turbulent.
Probably the only time when it is an actual problem is when people are drifting into some obstacle. It seemed to take students a matter of seconds to regain control of their boat when they were surrounded by large expanses of water. When they were frantic, their intuition about what they needed to do when in a hurry prolonged their loss of control.
http://www.sailing.org/tools/documents/42Interpretationsforb...
The larger projects I've worked on have typically used Perforce, but I used Alien Brain (which is pretty terrible) for some of the older ones. The check in/check out workflow, which is the same in each case, is basically what makes it all work once you get past a handful of people. Just simply being able to see who else is working on a (almost certainly perfectly cleanly mergeable) file that you're contemplating modifying is a big time-saver.
(I've used SVN, at a much smaller scale. It has similar Lock/Unlock functionality, which is a good start, but the performance in general of that seemed to be really bad. Locking a few hundred files might take a full minute, for example. Meanwhile, Perforce will check out 1.9 gazillion files in ten seconds, and that's only because it takes nine seconds to change NTFS permissions for that many files.)
Well, I actually don't understand how you can make it NOT work :) You obviously have to work with branches split per projects/sub-projects and different repositories for different apps. You have to find your branching model that works for you, it doesn't always works with a dev branch (we don't do that, we have bug, feature, release and master branches).
SVN is so out of this league that I don't even try to understand why people use it.
If you're just going to make a quick tweak, you'll probably risk it. Either they check it in first, and you've got a very minor merge, or you do it first, and they've got a similar minor merge. Not a big deal, in either case. (And when your gamble doesn't pan out, tough luck. No sympathy from anybody. You knew the risks.)
But, if you're going to make a very large, sweeping change, you'll probably be a bit more cautious. And that's fine: you can go over and talk to them, or message them, or email them, or whatever, to find out what they're doing, and coordinate your modifications appropriately.
I've literally never once found this less than somewhat useful. It's, like, the source control analogue of static typing: a huge pain in the arse if you're not used to it, but, if you've seen it play out, it's a mystery how anybody gets any work done in its absence.
(Of course, if you use git, maybe you can just email/Slack/etc. everybody on the team before you go to edit a file, just in case, and then wait for anybody to mail you back before proceeding... well, I don't deny that would work, assuming everybody checks their mails/Slack/etc. regularly enough. After all, I hear people get work done in dynamically typed languages too! But just think how much better things could be, if the version control system could look after this for you!)
My one real pain point with it isn't so bad, but I dislike how perforce tends to work at a file level instead of a commit level. It's hard for me to make several related changes which all touch the same files, like a series of patches which all refactor the same area of code, but which I would like to review and discuss separately, and potentially revert some/all of.
It's hard to manage this with shelves, because perforce can't handle unshelving the same file in two different CLs. I could submit all the changes to a separate stream, but perforce streams just don't usually work well for us, and it's still hard to experiment by constantly making and rolling back changes.
I guess I'm probably only used to this workflow because I have experience with git, but this is the time when I really miss the granularity of a git commit (and I'm doing a pretty gigantic refactor right now... so it's hitting me quite hard).
I simply started a git repo in the same base directory as the SVN repo, and did my work in there. Every time I merged a branch back to master I committed to SVN's ^/branches/dev. Just add `.svn` to `.gitignore` and `.git*` to the SVN prop ignore.
You _will_ want to merge from upstream (Whatever Perforce's equivalent to `svn up` or `git pull` is) often, I was merging from upstream before every SVN commit (SVN mostly forces you to do this, `svn status --show-updates` is a huge help here but I don't know if Perforce has a similar feature).
perforce's APIs are actually pretty good as well. they aren't documented that well, but they are easy enough to build some complicated tools with.
I found the APIs generally a disaster, and rapidly gave up on them. It was much easier to just run p4.exe and scrape the output. But... oh god. That's not saying much. The command line client was shit too. It eventually proved possible to get everything I wanted, but the data was never quite in the right format, the available queries were never quite suitable, and the results were never quite normalized enough. In the end I had to run p4.exe several times, discarding a lot of redundant data while doing this, and then cross-referencing the multiple sets of results afterwards to get what I wanted.
(One thing I had hopes for initially was p4's supposedly Python pickle-friendly output. But this was no good either! - since, from memory, p4 produces multiple pickles'-worth of data in one go, but Python will only read one pickle at a time, so you couldn't actually read it in from Python without a bit of work. Really made me wonder whether anybody actually tested any of this stuff. Really felt like the thing had been coded by a bunch of Martians, working from a description of the process made by people who'd never used Python and weren't even programmers in the first place.)
When exploring ideas I might have 3 or 4 possible paths and it’s really nice to have the option of breaking them into different branches until I figure out the right path.
With TFS and SVN, it's already enough to have stable versions you need to backport fixes and the occasional feature to in order to end up in branching hell, for example.
This is true of basically all problem domains: "Why isn't X easy? Can't you just do Y?" And it usually just indicates that the person asking the question doesn't appreciate how difficult and nuanced a real solution to X is.
Real-world problems are often difficult and have non-obvious, sometimes-intractable challenges. "Easy" solutions often cause more problems than they solve — there's a reason why more complicated tools like git have taken over from less-capable tools like Subversion and CVS.
in git, for example, why can’t i switch branches with uncommitted changes? it makes no sense why i can’t do that, but yet, there it is.
> there’s a reason why more complicated tools like git have taken over from less-capable tools like Subversion and CVS.
i don’t think the reasons have much to do with usability or even capability. i came to git from perforce, where the latter was much easier to use, reason about, fix issues, and has much better tooling, in particular visual tools. it’s also amazing how slow git is.
Except you can?
[stouset:~/Development/some-project] some-branch(+8/-4)+ $ git status
On branch some-branch
Your branch is up to date with 'origin/some-branch'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: path/to/file1
modified: path/to/file2
no changes added to commit (use "git add" and/or "git commit -a")
[stouset:~/Development/some-project] some-branch(+8/-4)+ $ git checkout master
M path/to/file1
M path/to/file2
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
> i don’t think the reasons have much to do with usability or even capability. i came to git from perforce, where the latter was much easier to use, reason about, fix issues, and has much better tooling, in particular visual tools. it’s also amazing how slow git is.Perforce isn't free. git's popular predecessors were.
That said, I've found in my experience that way more people seem to hate Perforce than seem to hate git.
See https://stackoverflow.com/questions/22053757/checkout-anothe...
Because the working tree having uncommitted changes being blown away would be terrible data loss or a conflicting merge, so when that could happen, git prevents it.
Use `git stash` to stash your uncommitted changes before switching branches and you'll no longer have data loss.
If you want to apply those changes again use `git stash pop`.
If you don't want those changes use `git stash drop`.
Why isn't there a commandline option to checkout a branch and do a stash operation at the same time?
Because no one has needed it enough to add it.
Or because those that did need it whipped up a quick and dirty alias to cover that use case.
You can, if the changes don't conflict with the branch you're changing to.
Upvoted because this is so true, yet it is also only half the story -- let's call it the ignorant or lazy users half. The other half is the ignorant or lazy developer side: that is, developers who don't properly prioritize the 90% use case, and who don't appreciate or understand the natural mental models they should be accommodating and treating as problem constraints.
> they needed to be convinced that curation and management of source history was one of their job responsibilities, which was tough because it really wasn't previously, at least not in any meaningful way.
Getting people to be responsible for the whole is hard.
An email I got the other day was "we can't debug problem with x because it's built on the CI server" and the problem was in the first few milliseconds of startup so "attach to process" was no good, even if they knew that was possible. The idea of using a debugger outside of the IDE (mdbg in this case) never crossed their mind.
IDE's a great for coding, but too many devs are way to reliant on them.
It is so weird that in the 90s I could do MORE in my IDE than I can today, somehow our tools have trended to increasing complexity while IDE advancement has come almost to a stand still, with a preference to simpler less integrated ones (e.g. VS Code).
Enter the Jetbrains IDE. The same basic program for almost every programming language and a terrific VIM plugin to boot. It's on the order of $100 per year. Well worth the cost, and the only non-FOSS code on my computer other than the MP3 codecs.
I usually don't use the built-in Git commands in PyCharm, but I do use the built-in terminal to perform Git operations. The only Git work I do with the IDE directly is resolve merge conflicts, because that specific tool is terrific.
It's not so much that git is a leaky abstraction as it is that git isn't an abstraction. If you don't know what a DAG is or how commits, files (e.g., blobs), trees, etc. are mapped into the DAG, of course you're going to have a hard time!
Three examples (that cover 95%+ of use-cases):
$ git checkout some-branch
> Updates the index and working tree to reflect the contents of `some-branch`, and updates the HEAD pointer to indicate we're on the `some-branch` branch. $ git checkout -b some-branch
> Updates the index and working tree to reflect the contents of `some-branch`, with the "convenience" of creating it first through wrapping `git branch`. This is identical to calling `git branch some-branch; git checkout somebranch`. $ git checkout <optional-commit> -- path/to/a/file
> Updates the index and working tree to reflect the contents of the named file on the current or named branch/commit/tag/whatever.TL;DR, `git checkout` has a very clear and well-defined responsibility: update the filesystem and index to reflect the contents of some commit. Various flags and options cause it to perform reasonable variations of this core responsibility (create a branch that doesn't exist first, or update individual files rather than the working tree as a whole). If the commit-name provide is a branch (and you're not checkout out individual files), it also updates the HEAD pointer to point to the named branch, so git "knows what branch you're on".
I would be absolutely astonished if you could write the git internals (or even just knew how they worked) and the idea of a tool to make the filesystem look like the internal contents of the repo wasn't immediately apparent. You might not have realized that that's all that `git checkout` does, but once you understand that, it's extremely straightforward.
So, the checked out commit is the second ref specified, or HEAD, unless the flags are such that you can only specify one ref.
Git checkout also "merges" uncommitted changes with your new HEAD, which you didn't mention and makes me wonder why the command isn't called "git merge".
Git's main abstraction is the fact that everything is a content-addressable blob. This "leaks" but it's not a major contributor to the problems people have using Git, at least from what I've seen.
That is not the problem with Git. Mercurial or Darcs also force you to deal with it all the same yet are not anywhere near the UI clusterfuck that Git is.
> This "leaks" but it's not a major contributor to the problems people have using Git, at least from what I've seen.
It absolutely is, because it leads to commands having unintuitive and incoherent behaviours and thus to the porcelain being impossible to model top-down.
Which would be a reasonable attitude for your average driver but not for a professional mechanical or automotive engineer.
Unless I'm misunderstanding, you seem to be saying that being a programmer implies having a desire to understand every program's internals. But I don't care how Photoshop stores the 30-layer document I'm editing, and I feel like I shouldn't have to. I can't see why Git should be treated differently.
We insist, especially when hiring, that programmers know something about the internal design of other software that they use, but don't develop, on a day-to-day basis. Any programmer, depending on programming specialty, that doesn't have some idea about design of their operating system, networking stack, databases, or hardware would flunk out interview processes (and probably rightly so). The reason we insist on this specialized knowledge is because most of the time these things work fine, but when they don't the good software engineer proves their worth by being able to dig deeper.
Version control software is used just as frequently as any of this other software. But somehow there seems to be this feeling that it's not worth learning about and should just be a black box (I think package managers are treated similarly). Understanding git internals and design is a valuable software engineering lesson in and of itself.
The other aspect is having knowledge of Photoshop file formats is of limited utility unless you're an Adobe employee or Gimp developer (I don't know if the spec is open or not). Photoshop itself is closed-source and not so extensible or scriptable as an open-source command-line tool.
That's not true for git - knowing git internals reaps productivity benefits in your other work too. Treating it as a black box robs you of the knowledge to do some really cool stuff.
Broadly speaking this applies to any other software tool used by programmers - the more you know of its internal details, the more proficient you'll be in its use.
So in both respects (practical and from a learning standpoint) I think knowledge of git internals for a git-using programmer is a desirable thing.
git is unique in its apparent assumption that it's nothing more than a series of convenience scripts that let you work on the raw filesysten representation a bit more easily. In a way it's more a filesystem-level representation of a DAG with some sugar on top, than it is a DVCS.
Ditto. I've used Darcs, Mercurial and Bazaar, all are distributed, all have various levels of issues, but none of them required that I understand everything from the storage model up in order to actually get a grasp on them. I still have better intuition for Mercurial than Git (and long for a number of its features like GIVE ME FUCKING REVSETS ALREADY) despite not having seriously used Mercurial in years and having no idea whatsoever what goes under the CLI (and not caring a whit).
For developers that includes version control and package managers, amongst other things.
Do you need to know how git is implemented? Of course not. No more than you need to know how your compiler converts source code to executables.
...but understanding the basics of the tools (eg. what paths and layer groups are, to compare to photoshop), isn't something you can just wave your hands in the air and say 'not my problem'.
Its your job to know this stuff.
For example: in this case, knowing what a branch is, how to create and delete one, and how to merge with one is necessary. Knowing that the branch identifier is a hash, called a "reference" or similar jargon and what that entails, internally, is superfluous and adds pointless complexity: if that's really required then git isn't good. I have more important things to think about as a developer than what internal machinery operates git.
It's also kind of silly to call git's terminology "non-standard". Git was the first truly widely used DVCS, so if anything, git's terminology is the standard terminology by definition.
That could be extended to other tools like firewall configuration, TLS setup, library details, logging configuratoin, monitoring, etc. But you won't get very far in fixing any problems if you don't read documentation and investigate further.
You don't need to know the format of git pack files or the network protocol in order to use git.
You do need to understand the concepts of commits and branches.
We all expect software engineers, regardless of specialization, to understand operating systems, networks, databases and hardware at a better-than-layman level. Try saying "that's just a tool in my toolbox, I don't care how it works" about one of those topics in an interview.
> Try saying "that's just a tool in my toolbox, I don't care how it works" about one of those topics in an interview.
I've met plenty of engineers who couldn't tell you how any of those things work at a low level, but still manage to maintain high-paying jobs. I've also had plenty of interviews where these topics never got brought up. Maybe that says more about hiring practices than anything else, but I think you're vastly overestimating the worth of that knowledge to most companies and individuals.
The question is also simply what you pay for and what is in a job description. To simplify, you have to pay a lot less for someone treating software solutions as blackboxes with known behavior then someone who understands what is done.
You can of course ask in an job interview about everything from compiler optimization to network intrusion detection to image processing, but you better should make sure that is actually what you need.
Shouldn't a mechanic have an understanding of how an automatic transmission works? Similarly, shouldn't a software developer have an understanding of how version control works? In general, a professional should have a very good understanding of the tools they use for their work as well as what they're working on.
> History is linear, full stop, and conflicts are handled by essentially forcing a rebase on commit.
This is similar to Perforce, but not something I miss. That forced rebase in Perforce has the very real possibility of causing breakages, and there is no way (at least in Perforce) to reliably handle it.
I also don't think history should be linear; the cheaper branching model in Git in my experience leads to people actually taking advantage of it; contrast this to Perforce, where branches were expensive: people wouldn't bother.
At least in the case of Perforce, the fact people didn't use branches forced them to put all of a feature into a changeset (Perforce's closest equivalent to a commit), which was usually way too much; this results in multiple, distinct changes being squashed together. The lack of cheap branches makes it hard to build a change off of two in-progress changesets, again because the system cannot efficiently represent that state.
And then there was just tooling: Git's add -p option for splitting off partial files into a separate commit, the ability to rework the convoluted history that came from my discovery of how best to implement something to something that encapsulates discrete changes that can later be reverted or cherrypicked gracefully (without reverting everything, unless that's really required) are to me, extremely useful tools that just don't exist elsewhere.
> Some admin does branching and merging and emails us if there are weird conflicts, we don't worry about that. Why make it more complicated?
(To be clear: this does not match my understanding of Perforce; branches there are possible without an admin.)
I just simply can't fathom why someone would want to have to go through another human for a branch. It seems like so much bureaucracy for something that, as Git shows, does not require it.
> why source control isn't a problem solved 100% by tooling in a way that requires little to no interaction at all. To them, hearing that they need to read a chapter about the internals of a source control system before working on a project
I think because, if we accept that history is not linear, and should not be represented as such, then history must therefore be represented as a DAG. A DAG, in my experience, is about the point where people start trying to cheat, for whatever reason, with incompatible and flawed mental models. This bites them in the ass at some point, and they can't understand what they're doing wrong within that flawed mental model, because the model itself is flawed. (And I see this all the time in software engineer, not just with Git. People are too quick to analogize permanently something to something else that is at best a crude approximation.)
Now, as another poster in the comments notes, I'd temper with the above with: some of git's tooling and UI could be better. The mix of "index"/"cache"/"staging area" to all mean the same thing, the variety of things "git reset" can do, etc. all are terrible UI on top of a superior model, but do contribute to the confusion newcomers experience. I hope some day this changes.
First add a feature flag for your feature, then you can have as many small changelists as you like.
I've had a very similar experience. IMO, your source control is an essential working tool, like your text editor, and you should be very proficient with it, but plenty of developers that I've met don't share that view.
I was on a team that was forced to transition from TFS to git. Among those who weren't excited about it, the majority of the questions, challenges and issues weren't even as far down the road as how to use git, they were mostly along the lines of "why do we have to do all this other stuff now? Today I go to this screen, click this button, my work is now safe and other people can see it." History is linear, full stop, and conflicts are handled by essentially forcing a rebase on commit. Some admin does branching and merging and emails us if there are weird conflicts, we don't worry about that. Why make it more complicated?
These folks didn't need git tutorials, they needed to be convinced that curation and management of source history was one of their job responsibilities, which was tough because it really wasn't previously, at least not in any meaningful way.