Git is too hard
changelog.com
changelog.com
Resisting GUI's is not a good idea. The trick to learning is to always have `gitk --all` or a similar viewer open in another window.
Also instead of `git add` / `git commmit`, use `git gui`, but for most other things stick to the CLI.
Having said that use a GUI, github desktop is terrible. It tries to make things easier and as a result takes you away from git's standard terminology, so it's impossible to understand what it does.
Something I found teaching other people is it helps a lot if you haven't learnt SVN before.
I disagree. In my personal experience, learning git took a lot of trial and error, but now whatever terminal I sit down in front of, I know exactly which commands I have to run to do what I want in git. When using a GUI, it's fine for the easy/common stuff, but if I want to do something more complex I have to figure out how to dig through the options provided by the tool to get the result I want.
"Show me the code". Or in this case show me the GUI.
Maybe the problem is just actually hard and the Git we have is the best current solution.
Easy: https://gitup.co
It makes things that are hard or cumbersome in the CLI easy and convenient.
Things I always do because I'm no longer afraid of mistakes:
- split commits at random points
- move commits up or down the branch
- squash commits up or down the branch
- edit commit messages
Less often:
- cherry pick against current branch
- delete branches (local and remote)
There are signinficantly more operations hidden there behind convenient shortcuts, but I don't ever (or very rarely) need them because it makes fixing mistakes so easy. And the only reason for advanced git usage I've seen is fixing mistakes.
IIRC there have been various papers on Git's crappy UI and at least one two rewrites (of the interface). Gitless is the name of one.
Oh, I forgot the most important thingof all: integration with tooling! QtCreator has support and shortcuts for Git with its commands, but not Gitless.
magit
magit
If you want to do something more complex, the reasonable answer is usually to delete the directory and clone again.
IMHO, a good git GUI would show exactly what commands are being run (so it is useful as a learning tool) and their result and allow it being used along side the cli.
I use magit extensively and it has all these properties.
This insight why git, like other tools, is stupidely designed.
The "wrong" defaults and UX is the DEFAULT, and each USER must learn it.
Meaning:
UX * N Users = Wasted time and money
---
If I present you a screenshoot of a (real!) business apps with mis-aligned buttons, some put in weird places that mean different things that them are supposing by their labels, that use non-standard interactions that mix different UI paradigms, with rare color combinations (aka: vomit palette) , all in a SINGLE window (!), you think the solution is resist a better interface? Why we mock "regular" users or their enterprise providers, but somehow can't with ourselves?
I don't know why so many developers live in constant Stockholm syndrome and like it, and resist any suggestion to improve.
When anyone ask me about the tools I use (specially asked when somebody look at me using the terminal), if I liked, i say "No, this is the bad and ancient way, but we are here, stuck on this.."
gitk is like an anchor for me to understand where I stand in given repo.
Make sure to set default view to display all branches and mark branch sides.
gitk --all
PS. git gui
allows you to stage changes line-by-line, not just by hunkI would completely disagree with this, anything that adds layers between you and git creates more opportunities for misunderstanding and corner cases.
Resisting a feature branch/merge workflow is what's a bad idea.
After growing up and becoming wiser I came to understand I did this all because I didn’t invest the time to learn how these complex things worked. It also made me feel smart to write more code. Big mistake.
I can’t help but think a little bit of this pattern rears it’s head as the motivation for things like git GUIs.
There will be a maintenance burden and no matter how careful you are there will be bugs.
I write scripts for complex but infrequently used operations and drop them in ~/bin
That said, sometimes when you are frustrated by having to add special cases to your code, it's not your fault, it's because you're modelling a badly designed system in the first place.
Explain why.
Within our lifetimes, an interaction most users have with a computer could be just thinking about something to cause an action. I don't want to have to see a GUI in my brain to do that. Similarly, not everyone likes having to use what is traditionally called a GUI.
For git, I prefer the CLI, though I use some helpers for completion, I have some scripts I wrote to show remote and local branches with their authors in different states of merge, etc. My guess is that in your GUI, you don't have that level of customization, and probably didn't even think it was an option. That's the problem with GUIs for me.
Thats why, not everyone prefer CLI, if you are the one who learn better with GUI then resisting GUI's is not a good idea
The problem, at least for me, was the complexity of the model which makes the whole thing super scary when you've just started using it. That's where GUI tools come useful, as people are generally less scared of GUI tools - they make you feel there's less of chance of making a mistake because you put the trust in the tool to stop them doing something obviously stupid. However IME that trust is not really deserved as most of the GUI tools will just as happily let you mess up your repository...
Then go back to your force-pushing colleague and tell him to resolve the merge conflict he created by thinking he was too clever.
Examine the output of that command in detail before declaring your work to be lost.
You have to understand a lot of things before you can somewhat comfortably use git, much more than something like P4.
You also need the log daily to know things like "what changes made it into this build", or almost everytime I fix a merge conflict, to understand why something is the way it is.
I can grant that cherry-pick & blame are more rarely used, though blame is often on by default in many editors, and cherry-pick is something my team does daily around every release (since we don't want to merge the trunk into the release branch the day of the release for 1 bugfix).
So which would you recommend?
Oh, there is also the option of enabling autostash I think, but that is relatively recent (maybe 1 year?)
In case you weren’t aware, stash is not as safe as other git commands, it doesn’t have the same safety net and reflog support as a commit does. It’s relatively easy to drop stashes accidentally and lose them forever. I’ve seen people do this in production by not being careful when pulling while they have a dirty work tree. The man page for git stash mentions this fact:
“If you mistakenly drop or clear stash entries, they cannot be recovered through the normal safety mechanisms. However, you can try the following incantation to get a list of stash entries that are still in your repository, but not reachable any more:
git fsck --unreachable |
grep commit | cut -d\ -f3 |
xargs git log --merges --no-walk --grep=WIP
”Otherwise yes, I know you can relatively easily lose work with git stash (I actually once lost about 2-4 days of work with a P4 shelve, which is an extremely similar feature), but it still seems easier to me than committing and then cleaning up history/resetting if you change your mind about the implementation...
Perhaps I will give this commit/reset workflow a try as well, to see how it feels. It may also be that committing still feels to much like "an event" for me, from my P4 days.
Aside from that, I hear you, git’s model is fundamentally different from Perforce. There’s no choice about whether you need a clean work tree before pulling, that’s simply a git requirement. So the main thing to ask now is what workflow you want and what safety net you want underneath it. On one side, the best way to focus is to not pull anything while you’re working and have a dirty work tree. But things come up at work, that’s not always realistic, so the next question is how to make the workflow both safe and also instinctual so that it doesn’t have friction.
I do think there’s something to your notion that commit feels more serious and heavy than stash, and that is something I personally have tried to break down. In git, commits and branches can be so much more lightweight, fluid and flexible, but it takes practice and fluency in git to be able to actually feel that.
It might be worth considering some shell or git aliases to do common things. You could easily alias a command that commits your work in progress with a comment “WIP”, and never have to type it. You can do the same with a branch and even keep around a branch for work in progress that is always temporary and gets force reset to whatever you’re working on. (Remember a branch is just a pointer and nothing more, you can completely change what it points to without hurting anything, and the change is stored in the reflog, so there’s a undo button.) I think it is possible to make a branch & commit workflow that is both easier and safer than stash.
More typically, I will "git fetch origin" to fetch the current integration branches, then "git checkout -b <feature branch> origin/master" to start a new feature branch from a given integration branch, then push that once the change is completed.
If I need to update a local copy of an integration branch, then I might well use "git pull". But I would never have any local changes made there which would require stashing, since all changes are done on feature branches.
I think diffs are faster if it's to the local repo vs the remote repo.
I always make branches off local-main, as opposed to remote main as in your example.
I think it's also helpful to have the main branch replicated across as many machines as possible. There have been one or two times where a dev has deleted remote main at my company where some (very VERY CALM) git push solved the problem. I probably could have checked out a tracking branch and fixed it that way, but having a local copy of main made it a one-step process (I think the resolution was just to git push the main branch?).
Alternately if I'm helping other developers, I'm on their branch a lot, and it basically becomes a "push your changes and I'll take a look" and I just open that folder and git pull.
I think I use more git pull now than I did originally, because I'm working on less of my own code.
I would be very happy if I could just merge to master every day, but that is extremely rare for me and my team.
If you take out the concept of builds, you just have short lived feature branches off of master, you're left with perhaps even less than the 8 commands listed above.
Your uses for log sound legitimate but usually they are resolved over other communication channels (in person or over slack or in release notes) on the teams I've worked on.
If I want to have things-from-master in my current branch, I either rebase my branch onto master or merge master into my branch. (I'm lucky that my branches are short-lived enough that rebasing on top of master is almost always easy and the right choice.) If I have unfinished things, I'll make a "WIP" commit, that I will unroll later after doing the rebase.
I nearly never use `git blame` on the command line, but have a very frequently used hotkey bound to it in my editor to show the blame annotations.
At work we do care that our git history makes sense, is free of random nonsense, but contains only self-contained commits with reasonable documentation. So I call git log many times every day, I would not know how to do it without.
Cherry-pick probably depends how may maintenance branches you maintain. We don't have many, so I don't need it very often. I guess that could be very different for someone required to support long product life cycles. Sometimes when I need to split or unite development branches that need major reorganization I use it.
Blame I need soon when I try to understand others code. Sometimes even on my own. Also when you get bug reports form the field, to understand how long certain bugs existed. Not always to be able to blame the author, but just understanding how long a line has been unchanged.
Personally I don't use stash a lot because I'm not afraid of committing anything to my working branch. I can always fix the code or the history later. Or I make a temporary branch with a descriptive name than just stash. Some use stash more frequently I have noticed.
Rebasing is always a good skill to know for when someone inevitably commits binary files or secrets to a repo and you have to do a bit of surgery to fix it.
Bisect of course isn't required knowledge but by god is it one of the most useful git commands a developer could know.
I've never used it, but it sounds like a nice tool of last resort.
It is actually a great first debugging tool for regressions (unless you already have a hunch where the problem is). It's usefulness is greatly enhanced if you keep your commits small.
But I have been in situations where I had to manually bisect the code because I just couldn't understand how the code could reproduce the problem, and having git bisect would have been a significant help.
As for `bisect`, it's magic. It is used to binary search git commits back to X point in time. You can use it to manually go through previous commands to find what code/how long ago a bug was introduced. You can also rig it up with a test command (say a unit test that you copy out of the working tree/keep in a separate worktree) and have it automatically sift through the commits and tell you the first point where it starts to fail.
You additional items are definitely helpful - but the typical team member's workflow won't cross those bridges. Team leads perhaps.
There's definitely levels of proficiency, but for a junior or even mid-level dev doing feature work, I think there red flags if they are needing to jump into stash, cherry, etc on a daily basis.
Also, git lfs and git submodules and their associated commands are necessary or not based on the project, not on your personal level of proficiency.
I also don't know of any workflow where you don't need to look at the log at least once every few days, even as a junior dev, to confirm if a bug is fixed in a build or not if for no other reason.
That doesn't seem great... Usually these days I try to put my temporary work on a temp commit or branch at least so I don't lose it to the stash. I'm not saying I'm stashing properly, just that stash is easy to mess up.
Also probably half of these are things I popped but had merge conflicts or something. I fixed the merge conflict why is it still there? (I know the reason, but still).
As well as being more descriptive if you come back after a long weekend, this also means that you can swap branches without worrying that your stash relates to a particular branch but doesn't explicitly belong to this.
git config rebase.autoStash trueI usually do all the work in branches anyways, so I'll just create a quick branch and commit it there.
I never work on a checked-out version of a branch that's currently being updated. I always check out a new branch for my work and rebase or merge off the branch others are working on.
I'm fully aware of stash, and every now and then I use it, but it's pretty infrequent. Seeing as you need to learn branching anyway it's not going to be important for every workflow.
git branch feature1 origin/master # create
...
git fetch --all
git rebase -i origin/master feature1
Also, use emacs's magit as a better ui. Even if you don't use emacs, seriously. It's fantastically easy and fast.Of course, to the point of this thread, that is yet another concept you have to understand to get a sane working environment. I assume autostash is disabled by default because the post-merge/rebase unstash could result merge conflicts and be a pain to unwind if you change your mind. If you just blindly set this option based on someone else's recommendation without knowing what the stash is, and things go wrong, you'll require a mental model of the steps involved to fix it, which you won't have.
So basically, I am proving the article's point.
Without stash, things can be nasty. Some alternatives:
1. Commit frequently, one tested piece of code at a time.
I'm sure this is what you meant. Not every environment and process allows this and not every change is small.
If you can though and have time, do this. If needed perhaps you can combine things and rebase later into larger commits. This is the reliable and clean process of development that everyone would love to have as a base, and then to do whatever they feel with it and it always stay like this with hard work and dedication.
Let's move on because that isn't always going to be the case.
2. Commit unfinished/non-working code.
The best analogy of this is like leaving unfinished crap all over the place that might look finished to some. At some point, it may go wrong. If you do this, you might name the branch with something standard indicating it's unfinished.
This always seems to happen when a developer leaves for a holiday/vacation or leaves permanently. Then some other developer tries to build/test it, it works, they smooth some rough edges and commit it. In my experience, it is was truly unfinished, the quality may end up being somewhere between a point on a line anywhere below the initial committer's typically code quality and anywhere below the fixer's code quality. There are exceptions, but as a general rule, be more careful with such commits if the personal investment and sense of ownership is not strong in that code.
3. Multiple copies of the repo.
It's likely going to be less efficient to have multiple copies of the repo from a storage standpoint.
Showing the stashes may be more efficient than searching through different versions of the files in copies of the repo or having to recursively diff repo copies.
Using multiple copies of the repo may also increase the chance of things going wrong or history being lost.
I still would recommend having a backup of anything really important in the repo at times, if you're not feeling confident or are worried about losing anything.
4. Throw away code changes.
Every time you switch priorities, you could throw away all of the work you had locally. If it was crap, this might be best. Be careful; you could lose something important.
5. Manually copy changed files to another area outside of the repo to ensure it doesn't get stomped accidentally.
This can be messy, but with tools to make it easier, it might be "ok". Compared to git stash though, it's likely less efficient, because whole files are being copied instead of just the changes.
6. Manually backup only the diff/patch files of changes.
Well, now you're just recreating git stash functionality, but sure, you could do that. People did this before git stash and still do. Create patch files. It doesn't sound as easy or clean, and you've got to put those patch files somewhere. Will that be consistent between developers? If a developer leaves or is unavailable, where would you find them?
The others I'd say could be completely excluded from daily/weekly/yearly use. If you are using cherry or blame daily then there is probably something wrong :D
Also, cherry is often needed daily in short bursts around releases.
Blame is rarer, absolutely, but I don't think you're using your version control to anywhere near its full potential if you don't use blame (and log) while investigating complex bugs.
- easier to merge and ship small incremental changes than large ones
- easier to revert small commits
- better commit messages since you can summarize the smaller change instead of "coded a lot of things"
- if you have a messy commit history in a PR you can squash them when merging upstream
I'm not sure what your git methodology is but I tend to avoid cherry.
We've got a clean production/master branch that we merge develop into on releases. We merge feature branches into develop. Very very rarely we may hotfix something on develop. I don't think I've used cherry in 6 or 7 years on repos with 2-30 active devs.
What are you using cherry for daily around releases?
And sure, it's easier to ship small features than large ones. But it's harder to follow one complex change as a series of short patches than one big, self-consistent change.
So to me, commits should be as often as possible, sure, but that is normally once a day or once every few days for serious features / large bug fixes. I usually want to pull or switch branch much more often than that.
And related to release time: typically we have a single main branch that serves multiple projects. When one of these projects is close to a release, they cut off a release branch that is feature frozen, in order to fix any remaining bugs and thoroughly sanitize it. In the meantime, other teams continue merging features into master as they are ready. Bugfixes normally also go into master first, and they are then cherry-picked into the release branch (or branches, if there are multiple releases overlapping). So for us, during this release window, cherry-picking is something that every team member does constantly.
I think the habit of committing more frequently stems from working remotely across different timezones and still making code review a daily habit. It is part of our async communication. If someone hasn't committed code for a few days I'd be concerned they were going down a bad path or getting stuck.
I may not even communicate with that team member outside of a PR for the whole week so that's where most of our communication happens if I don't see them in slack or zoom - which would be the case if our work hours don't overlap.
But hey! As long as what yall are doing works for you then no worries. No team manages their code the same way - which I'd say is another plus for git.
But the more appropriate way to discard changes is leaving them to rot in the commits of a dead experimental branch, avoiding to merge them into the important branches from which releases are made.
And conversely (at least in my experience), being very familiar with git makes it _really_ hard to work with something like p4.
In essence, P4 is a file tracker - you have remote files and local files kept in sync (git clone, git fetch, git pull). The basic workflow is to modify, add, copy or delete one or more files (git add), group the changes into a changelist (git stage), give it a description (git commit), and submit that change list to the remote (git push). Of course, if someone else modified the same files between your last sync and your submit, you will also have to resolve conflicts.
Of course, you can sync all or part of your files to some specific older CL (git checkout). You can revert a change on the remote as well (git reset). When you look at a file or directory, you can see the log of all changes that happened to it (git log).
The biggest difference from Git is in the branching area - branches in P4 are simply copies of one or more files, together with some metadata to tell P4 that this is an intentional branch. Working with branches is simply working with different copies of a file. When you want to bring changes from one branch back into the other, you can merge (integrate in P4's parlance) one or more changes between the branches. At that time, it does a 3-way merge just like Git - last common ancestor, changes in branch A, changes in branch B => result. The most common way of creating branches is to have each branch be a copy of the entire project dir (so you would see on your local system ~/p4/root/proj1/main,~/p4/root/proj1/dev,~/p4/root/proj1/feature1 etc.).
One limitation of P4 branching is that you can't really revert a merge in P4. You can of course revert the changes, but the merge is forever considered the new common base for the two branches. So if you integrate branch A into branch B, then revert the change on branch B, and then try to integrate again, P4 will tell you that all of the changes have already been integrated. If you try to integrate B into A now, it will try to integrate the revert into branch A.
And this is essentially it. P4 scales much better than Git, so most companies have a single P4 repo, and everyone syncs only the parts that they need.
All of these things can be done from either the command line (p4 sync, p4 edit, p4 reconcile, p4 submit, cp + p4 branch, p4 integrate) or from the very simple first party GUI, P4V.
It depends on your team's workflow, probably, but if you find yourself needing all of those daily, it seems to me like your workflow has some extra complexity that most people won't have.
I do agree that usually, when you have a local branch dedicated to a particular remote tracking branch, it's not a good idea to merge the remote into your local branch - it's generally much better to rebase your local branch onto the remote tracking branch (pull -r).
So I agree with you, the default pull behaviour that pollutes the branch with useless merge commits is plain stupid.
That or you could RTFM. That's what your coworker and the person writing on StackOverflow did.
While people could put in more effort to learn git more thoroughly, there is validity to the sentiment that git could be easier to learn.
Git might not be easy, but it's not complex, it's simple. There are basically only four concepts: blobs, trees, commits, and refs. Which systems (not just version control - systems in general) are simpler?
Git is simple, but not easy. I suspect this is by design. I vastly prefer simple tools over easy ones. Sure, you pay a little more up front in time and initial frustration, but ultimately you really grok the tools and life becomes easier.
Often, simplicity comes at the cost of being less user friendly.
It's harder to learn to drive a stick shift than an automatic, but the manual transmission is a simpler system than an automatic.
I use the first two so much that I've dedicated a keyboard macro key to each.
The main problem that I see with using git is that when you are part of a team, what kind of release and branching strategy should you use.
It's comparatively easy with one person team but becomes complicated with a team and even more if it's an open source project and now you have individual devs contributing their changes.
It avoids much of the confusion from the checkout command, which does very different things depending on what flags you pass it. That said, this is only one git command. The rest still has plenty of room for confusion.
They’ve also added some guiding comments to various commands (like rebase) that make the CLI more user friendly.
I think checkout was the worst offender, because of how necessary it’s use was for most workflows. Branch could probably use some pruning, too.
Avoiding the rebase/edit/ammend/etc cycle is a huge time saver. What I really want it to do is be able to select a random hunk and move it as well...
[0] which was created before my time at Axosoft, so I'm not that biased :-P
I disagree. It is quite slow and makes the wrong assumption that everything should be text.
The whole point of the UI is so that your workflow is simplified without having to understand the exact inner workings of it all.
GHDesktop’s simplicity means that most of time I don’t have to call 4 commands to just check out a new repository or PR because one click runs all those 4 commands and more.
As simple as it is, lately I rarely have to use the CLI (which however I still use because I rebase and fixup)
The fact that “takes you away from the terminology” sounds like people complaining that Windows 95 users don’t know what MKDIR means: That’s the whole point of UIs.
This sounds ominious.
The fact is, once I got over myself and sucked it up and got my head around it, it really only took 2 days of effort to grok what I was doing and now it's easy.
So biggest advice I can offer is this: Get over it and get on with it. It seems like a pain in the ass now, trust me I know, but you'll thank yourself for making the effort in the long run.
Thankfully there are tools that make it less horrible. Git Tower and Visual Studio integration come to mind as examples.
It's sad, however, that there's not been an overhaul of the git commandline into something coherent and usable.
You know what made it bearable? SourceTree, and I tried GitKraken way back when it was first launched in beta, it seemed like it was on the right track but lacked too many of the features at that time. I would highly recommend SourceTree though.
I think it really comes down to a difference in philosophy in terms of learning how to use tools. In the past, one had to read the documentation to figure out how to use a tool. So, for instance, running git --help or git branch --help would give the information needed.
Now having a what's considered an intuitive interface is expected, which is why many people have problems using tools where the documentation is there, but people don't want to take the time to read it.
This is rarely the case. Sometimes at the end you get nothing but a wet handshake. Think about vim: it is cryptic, does everything different than everything else out there , but it gives you something in return.
If you make your tool less inutive, but give users nothing in return, you are doing it wrong. If the interface of your tool does it one way in this corner and another way in that corner — so if you are inconsistent without good reason — you are doing it wrong.
Interfaces are about clear communication. Interfaces are the difference between a rugged 50k$ Arri Alexa cinema camera and a 200$ camcorder: the more Alexa has physical buttons and knobs for important things precisely in the locations where they should be, precisely behaving in the way they are expected. The cheap camcorder has buttons, encoders and levers sprinkled over it seemingly random.
The interface of a tool is good when it can be used intuitively even under stress, in bad weather and on drugs. This is ehat we all should aim for imo: tools that are more powerful/expressive AND more intuitive at the same time.
I like reading manuals, but not for things that could have been totally obvious if somebody spent a split second thinking about how to communicate it clearly.
The same could be said about git. For example, branching and merging is far better with it compared to previous VCS systems like SVN or CVS. And, like git, one had to read the documentation of those systems to have a good understanding about how to use them.
> I like reading manuals, but not for things that could have been totally obvious if somebody spent a split second thinking about how to communicate it clearly.
But should everything be totally obvious? For example, I doubt someone who hasn't read the documentation at some point could write a simple hello world program in most programming languages without making an error.
But yeah, I fear people have issues with Git because unfortunately they reflect upon their experiences with other SCMs (like Clearcase, SVN, RCS/CVS, whatever) and think the same terminology and concepts apply in Git and then it goes wrong.
Git is not really rocket science to use. People who find Git difficult or nonsensical should spend 4+4 hours of their weekend playing with Git while reading Pro Git. It's available for free at https://git-scm.com/book/en/v2.
Specifically, read chapters 2, 3, 5, and parts of 7.
You should intentionally skip chapter 10, more than likely you don't need it.
Keep Pro Git handy and come back when you've a specific need.
Git is the bad boyfriend of the developer community. If anything bad happens it was your fault. If you ask it to do something and it does something else, it was your fault, and also you are stupid. If you ever make a mistake, you will be punished for it with a long drawn out cycle of embarrassment. No matter what happens, it was not git's fault, it was your fault.
Good software is not like that. Good software is the opposite of all of that. Git is the industry standard, and I have just accepted that we aren't going to get anything better, but whereas it might make sense for the Linux kernel dev community, it is not good software, and I suspect that it's not just the UI that's the problem.
Lots of non-devs also have the problem of wanting to have multiple people edit the same document, track changes, and occasionally merge them. I would never recommend that they use git, and I see no evidence that it is ever spreading beyond the dev community in any significant way. There's a good reason for that.
I tried SVN one time, which is a little simpler, but still didn't catch on with the person I was showing it to.
IMO nothing remotely like version control nor anything that requires a command line is going to click for someone in a non-technical field.
rm -r some_common_dir/
or echo foo > important_file.txt
that would also be perceived as your fault. And yet, command shells are pretty good software.As for non-devs editing the same document - unless that document is text (which typically it isn't for non-devs), I would probably not use git on them either.
This is a contentious statement. Fred Brooks himself calls the separate command language, which began with JCL on OS/360, a mistake.
The author's idea of putting an abstraction on top of git is the way to go. As an analogy, Git is a great toolbox, but sometimes you need a plumber. I like how apt and apt-get came into being on Ubuntu.
The comments about the logical inconsistencies in Gits command line are a clue.
When is the last time you wrote a CLI utility and listed all of the commands, subcommands, and options to make sure they all had a consistent look and feel? Most single-author tools do not do this. It is a consequence of developing in a vacuum. Team-based development allows other eyes to look at it and say "why is checkout used during branch in a different way then branches are checked out?". Git came from, essentially, one person. That's part of it.
But that is also a legacy of Unix/BSD. Consider `du` and `find`. Both have an option for max depth, but is it --max-depth, -maxdepth, --maxdepth, -d, or -m (or even -L for `tree`). There is a lack of consistency that is a rite of passive for Unix/BSD acolytes that even Gnu didn't fix... C'est la vie? Or maybe a /bin rewrite? bahahahaa who am I kidding.
There's no question Git is a powerful tool, it just needs to evolve and gain some consistency. And I think the answer is a higher level abstraction. And for the love of Benji, NOT a GUI.
I think what's interesting is that, in the space of programming language development, languages that tend to have a more consistent feel across the language (such as Clojure, Python to some extent) tend to have BDFLs and came from a single person.
It is truly fascinating the number of ways command-line parameters have been handled over the last 40 years.
I think someone on HN should write a blog post covering the history of CLI options. Wait, I bet there are 50 if I googled...
You can't just say this without providing an example of what you think is good software, as, after all, good and bad are subjective and not agreed upon by all people for all things, as evidenced in this thread.
In fact, it's every fucking version control system other than Git.
Ready to be downvoted into oblivion for this, but: This is how a lot of the Linux/FOSS community is so it makes sense that Git is too, sadly.
Things have gotten a lot better with the attitude these days, but you know it's bad when StackOverflow needs to issue guidelines on being polite and how to answer questions without being rude/condescending.
This is the root of the author's issue. As another commented, git is born in a world where computers are mostly offline, people are highly technical, and will spend a lot of time manually crafting the messages they will send to the numerous collaborators. It is an alone-first software. What the author wants (and exactly what I want as well: https://news.ycombinator.com/item?id=25002318) is the complete opposite: a system that knows it's connected to other people, where changes are instantly propagated and easily visible, where the differentiator between "branches" is not "what computer does it reside on" but "who did it". That's the model behind GitHub, after all.
git is complex because it's working with a very complicated model that is not in line with what most people expect today. As I said in my other comment it seems that fossil works with that flow, but I haven't tried it. However what is sure is that it doesn't make sense to ask git to become what it fundamentally is not.
EDIT: There might be a solution with wrappers. When you look at git-annex assistant (https://git-annex.branchable.com/assistant/) you can see that the right amount of abstraction can provide something closer to what we expect... but at this point it's not git anymore, so we might as well start from scratch.
My previous and current company use perforce but many people (often those who recently join) are decrying that perforce is less elegant than git, but, realistically and based on your own criteria it would be "better" for the connected case.
I'm personally a big fan of 'offline/local-first' being a thing, but I'm a sysadmin not a developer.
There is locking but it’s seldom used- handy in the gaming industry for code which depends on data.
I also find git's default of rewriting your worktree when you switch to a different branch extremely annoying compared to simply having each branch be a different directory in the FS. Fortunately, digging around I recently discovered git worktree and I'm much happier on this front at least.
The file locking was always a relatively obscure workflow, so I'm surprised that you even had to see it if you didn't use P4 a lot. I've only seen it in 3 occasions: working with binary files, the error message when I didn't actually have write access, and when someone intentionally locked some files to make sure they don't have any merge conflicts while they finish up a huge commit.
but what was the issue with `p4 edit` that caused you to write a new CLI tool for checking out files?
I have my problems with it, but once you understand it I find the workflow quite simple.
If you don't really need the decentralization I think it aligns quite well with how people expect version control to work. You make edits to your data, once you're done, you send them to the server to be shared with other people.
Ugh. The centralized model is better for companies, but ClearCase really makes its best to make your life miserable:
- You have to think twice before modifying a file, because the steps to be able to modify a file can take from 30 seconds (if you already created the activity) to a few minutes (if you have to create it)
- Activities are supposed to be like branches, summing up all the changes. But there is no way to see all changes in one go. It's click everywhere, waiting for the server to reply on each click.
- Because there is no way to display the branch content in any way other than envisioned by IBM, there is no way to discuss a changeset. No pull requests, no exchange, nothing.
- Horrible UI/UX all around. It's slow, it's unreadable, random bugs happen all the time where the only fix is to restart the service, .... and it's expensive.
I'm not advocating for a system that only works when online (although the fully integrated system of Google does sound good), just that it be architectured around a point of centralization. This is the way I'd like to use git:
- A branch created locally will be synhcronized and visible to everyone by default
- A branch that I manually tag as private won't, but it will still be saved on the server
- A branch that has a conflict between me and someone else will be marked locally in some way (maybe a second branch ?)
- Bonus: my working repo and staging area are also synhcronized to the server
>Oh, I just pushed a change. I really didn’t wanna push that, so how do I undo it?
Is a Github problem, not a git problem. You might as well ask how to unsend an email. If you don't know what git push means, you shouldn't be using it and are playing with intellectual property fire.
The conflation of Github with git is responsible for a lot of confusion. Having Github be your first interaction with git is a disaster.
Regardless, there's no shortage of blog posts complaining about git being hard. But there is a shortage of effective, popular competitors. I think that, actually, many-chefs many-branch differential version control is just a hard problem and creating a simple model for it is much harder than complaining about git.
With history if you make a vcs mistake, or realize iteratively after pushing that corrections are needed, your worthless threshing around trying to fix it becomes part of your project log forever, instead of just pushing the corrected tree with just the one corrected patch.
History flow will show all the meandering around forever, but rebase will remove it and just put the most recent version of the commit on top of the tree. Ie, your log looks like you pushed just the perfect patches each time, every time, and the junk is gone.
I would also like the ability to see a nicely curated set of changes. This mostly exists in the diff tabs of a pull request. If this were to be a first-class feature in git, it seems appropriate to be in some layer other than commits, but alas, that doesn't exist.
But casually manipulating the order of, or combining or filtering, patches near the top of the tree is something else. There are tools for this, eg
I routinely do an interactive one before PRs to clean things up.
If the remote branch is an ancestor of your local branch, you have some commits that haven't been pushed yet and you can "play" with them.
If the remote branch and the local branch point to the same, you can't rebase without potentially impacting someone else.
If the remote branch and the local branch have diverged, it's already too late.
If it's rebased then you're not reading the history; you're reading an artificial modification of what actually happened, performed by someone (possibly past-you) who thinks they know more about what you're trying to do.
I don't rebase precisely because I want to read the history to see what happened.
Do you mean it's a problem only if you are "git push'ing" to a remote shared by those working on a software project?
OK, maybe. Even before github, most projects I knew of using git used that method. You can suggest nobody should, and try to educate people in a completely distributed workflow if you want, I suppose. That's not about github really.
The Github-first problem is viewing git merely as an interface to Github, where the home of the work is and where all things are collected and operated on. From this it follows that git push is a fundamental operation like add or commit. And from this follow complaints that git commit isn't something that sends your changes to the One True Repo.
If you push then you should give up any expectation of control or ownership over the code that's sent over the communications protocol of choice. Purging a file is nice for you but in action would be a force-pushed rebase that you have to ask people very nicely to use instead of the initial branch. Controlling what branch other people use is completely out of scope for a local VCS.
The blog continues on to say that the distributed nature gets in the way of the mental model.:
>they have never even considered that there’s such a thing, because why would they? A branch is just a single concept in our head that is made complicated by the inherent distributed nature of Git.
And that's just the wrong model to have, inspired by understanding git through the lens of Github. If you're using git and you're unaware that you're operating on your local copy, not a shared workspace, then you can't place much stock in whatever mental model you come up with.
It still has nothing to do with github specifically. It is also true of people using gitlab. Before github existed, I (and many other teams I know) used a variety of other ways of hosting a remote git server shared by the team, including various open source software with web UI, as well as no web UI at all, remote git accessed via ssh (`ssh:` git urls) with no other UI.
The issue applies to all of them. And again most teams I knew were doing this before github existed. It applies to teams using gitlab or bitbucket or other in similar ways now too.
I still don't thinkit makes sense to blame github specifically , as I believe you are doing, for the way most teams choose to use git -- since before github existed, and still now using a variety of software choices in addition to github.
So, no, GitHub didn't create this, but it made it default
I'd wager I press the "undo" button in gmail at least 3/4 times per week
Also, may I kindly suggest that you aren't putting enough thought into your emails? That may be fine for single-recipient emails (depending on your environment), but when your email is received by many people it's an unkind act that shows disregard for the recipient's time and attention.
most of my e-mail are just chat conversations with a title
After it actually sends the e-mail, there's no going back.
Question from the blogpost: "I git pushed and I want to undo it"
Compare with: "I uploaded the file on the server with FTP, overriding previous version. How do I undo this?"
Or: "I did 'svn commit', how do I undo this?"
Or: "I have sent an email. How do I un-send it?"
I am not sure where does the original author's expectation that you can undo any action comes from. "thrwyoilarticle" seems to says this is because they started from "github" interface which has nice friendly UI which warns you about actions which cannot be undone. This sounds reasonable to me.
That is also a reasonable request.
I'm unable to fathom the notion that if a computer doesn't work the way people want, the answer is for people to adapt to the computer. The whole point of computers is to do things for people.
With physical messages, unsending has at least partial support. Before the mailman picks up from my porch, I can grab a sent message any time. If you FedEx the envelope, you can cancel before delivery. With a university's mail system, you can get the receiving department's admin to return something even later in the chain. And of course, you can always tell a recipient, "Hey, I sent you the wrong box, just send that back."
The reason email doesn't support unsending is not some essential property of messaging. It's just that at the time our email protocol was defined, both our hardware and software was pretty primitive, so we locked in a very primitive model of messaging. But note that more modern systems, like Slack and Facebook Messenger, happily let you unsend things. And consequently, they're effectively replacing email for most users.
email supports unsending in exactly the same ways you described for packages. It most definitely is a property of messaging.
Your fron porch is called "outbox". works the same - you can delete from outbox before sending.
If both you and your recipient are on a properly configured Microsoft Exchange server, you can unsend a message, which is similar to the university department.
And if you aren't, you can still send a message saying "hey, please don't open the last email", and it's up to the other side if they do or don't.
For better and worse, email has a lot of similarity to real mail, down to the distinction between content and envelope.
The main difference is the speed of delivery - you would not expect any of the ways you suggested to work 3 months after you've sent your package -- and yet, compared to the 500ms or so that it takes the email to reach the recipient, that's what attempting to unsend after one minute is.
Asking "How do I unsend an email" is just as unreasonable as asking "Hey, give me that gift I gave you back".
The problem is that, regardless of your intent, you've given something to someone and they own it now.
You can't undo that without involving the 3rd party (Or breaking the law and stealing it, digitally for the email).
And I want to be clear upfront - THIS IS A GOOD THING.
I don't want Amazon to be able to "unsend" my receipts. I don't want Google to be able to "unsend" my support chat log. I don't want my boss to be able to "unsend" his approval for my time off.
This system is designed explicitly to put the USER first. But it treats each side of the exchange as user, and values them equally - If they disagree, it's not the system's job to resolve that, they have to talk it out.
Slack and Messenger (and a lot of other modern chat) have an arbiter - They don't require users to agree because they own the content, not the users. In a company slack, I haven't given you anything when I message you. I've just pinned something to the company message board. I can take it down, and so can anyone else who has the key. It's not mine and it's not yours - It is very clearly owned by the company.
That can work great in a well structured environment, but I have to laugh when you say its replacing email. It's not a replacement, it's a complement - They are not the same things.
Just like an oral promise with no witnesses is NOT the same as a signed receipt. Use each as needed.
This doesn't mean that Git has to accept any feature under the sun and it might be that Git isn't most appropriate tool for teams that want such a feature. But there's nothing holy or fundamental about an implementation detail of how Git does things that makes their use-case hard.
A VCS shouldn't be unnecessarily difficult to use, but the fact that this conversation around Git's UX is endlessly rehashed is proof that version control is a hard problem.
If there was an easy and obvious 10x improvement over Git it would have replaced Git by now. Or to put it differently, when someone makes an easy 10x improvement over Git, it will see widespread adoption.
The same was true with the switch to WYSIWYG OSes and word processing tools; they were generally liked by people new to computing, but people who were steeped in the old ways, many switched only reluctantly.
If you take it away from me, or make me later inadvertently push their code, you are inconveniencing an innocent person.
Yes, yes there is.
I've worked in systems like you're describing (CVS, SVN) - The problem is that they ALL require locking.
Locking freaking sucks. It sucks SO INCREDIBLY MUCH more than dealing with the complexity of a real distributed system that git won, even though its cli interface is a god-damned nightmare.
You clearly haven't had a co-worker lock a file you need to edit and then go on vacation.
Laugh all you like, but kids and the interns I've chatted with see email as something akin to how I feel about fax machines: not something they'd use by choice, but necessary for historical reasons. When I've been at organizations during a Slack adoption, email volume drops hugely; 50-80%, I'd guess. I've closed most of the mailing lists I used to run because they shifted to mediums better suited. Just this morning I had to FB message a few friends to get their current email addresses, which tells me a lot about who's winning.
Yes, I agree there are times you don't want things unsent. And there are times you do. There are a variety of ways to balance these concerns. But exactly none of them involves saying, "Lo it was handed down to us by Postel the Wise, and none shall tamper with His choices."
Asking to unsend an email is a reasonable request. The answer could be yes or no given the circumstances, but it's only an absurd question to people who have taken a 1980s technological choice and treat it as some sort of unalterable gospel. It reminds me of this Douglas Adams quote:
"I've come up with a set of rules that describe our reactions to technologies: 1. Anything that is in the world when you’re born is normal and ordinary and is just a natural part of the way the world works. 2. Anything that's invented between when you’re fifteen and thirty-five is new and exciting and revolutionary and you can probably get a career in it. 3. Anything invented after you're thirty-five is against the natural order of things."
Sure, I get that a lot of people were born after RFC 822, so it seems like the natural order. But the people who wrote the early RFCs weren't thinking that way, and neither should we.
At no point did I appeal to authority or history in my argument above, so drop the shit around
> "Lo it was handed down to us by Postel the Wise, and none shall tamper with His choices."
---
If you think Chat apps are winning, let me know when you can buy an item online without an account linked to an Email. I'd love to see an example.
You jumped into a discussion. The person I replied to was treating the email we happen to have as some sort of unchangeable given. That's what I am objecting to. If you are disavowing that side of his argument, feel free to say so, but it looks to me like you lean pretty heavily on it.
> let me know when you can buy an item online without an account linked to an Email. I'd love to see an example.
You mean aside from the billion or so users of WeChat Pay?
> [Chat apps] can work great in a well structured environment
> Use each as needed
> I also tend to use discord/steam for throw-away conversation with friends
Yes, clearly I'm only advocating for the use of email in its current form for all communication, see me lean so hard above?
---
Wechat might as well be the Chinese government, and it requires a Chinese/Hong Kong bank account to use Wechat Pay. If the government won't honor your transaction record, keeping a copy yourself isn't very useful...
https://www.amazon.com/gp/help/customer/display.html?nodeId=...
And SMS operates with the same functional principle as email - I own the text after receiving it, and can use it as needed.
You can do pretty much anything you want in WeChat, and you don't need an email.
Given how tightly integrated wechat is with the chinese government, and the restriction of wechat pay to use with folks who have a Chinese/Hong Kong bank account, we're talking about different levels of utility around preserving the record.
If the government chooses not to honor your transaction record, it doesn't really matter if you have a copy yourself.
You can “unsend” on those platforms because the GUI does not display files saved locally, it always fetches them from the server. If you could “unsend” on a version control platform, then it would cease to be distributed version control. The code would have to live inside the VCS app (the same way messages are in memory in slack), or you’d have to give a network daemon delete privileges on your file system.
Imagine if youtube-dl used the model you’re proposing. Letting the git equivalent of “unsend” propagate through the system takes you from a redundant system to, not a system with a single point of failure, but even worse, a system with many points of failure.
Git is for helping develop open source projects, where sometimes a random gal who will never show up again fixes a small thing and sends the maintainer the diff through email. If you want a tool for the high trust environment of your individual team, git will never be what you want. It literally wouldn’t work for its intended workflow if it did what you want.
Without trying to be snarky - All your comments directly ignore that what you're proposing values one stakeholder more highly than another.
People keep pointing out that there are two users involved in this exchange, and they both weigh equally, and you dismiss them and talk about running mail servers 25 years ago (who cares?).
You keep saying "I should be able to unsend my email". Let me rephrase your question - Why should you be allowed to delete my email?
>Asking to unsend an email is a reasonable request. The answer could be yes or no given the circumstances, but it's only an absurd question to people who have taken a 1980s technological choice and treat it as some sort of unalterable gospel.
---
We're here answering affirmatively that "No" is the right answer for a LOT more reasons than an appeal to authority and history, and you accuse me of a strawman?
I wish you the best in life. Have a good day.
When I use my Gmail account to send an email to another Gmail user, this is obviously not the case. Many adults in their twenties have never used a desktop email application - at my company the younger new hires need some time to figure out how to use Outlook, and they're engineers. They've grown up with the cloud as a given, local storage as the exception, and centralized messaging apps as the default method of communication.
I'm not going to argue about whether way of thinking about computing is any better or worse, but undeniably convenient, and it's definitely the direction we're headed.
You don't understand because you think you're fighting computers but you're actually at odds with other human's desires.
If I pull your code, even if it was a mistake I don't want you to later rip the rug out from me and force me to figure out what happened from the history you deleted.
You can easily change the history technologically. You just force push what you want. The issue is that is usually disabled because it causes a lot of problems for everyone else on the team.
I also don't think what you said is necessarily true. If person A has pushed and nobody else has pulled, then for most situations there's no reason to prevent A from un-pushing. Even if person B has pulled, a propagating un-push might well be what they want. I generally would. There are certainly some cases where B might not want that, but given that undoability is a has become a strong user expectation, I don't have particular reason to believe that balancing users needs would come out in favor of the current behavior.
Gitlab and Github (rightfully imo) came to this behavior. It was not random and is not the default git behavior which is to just allow the force push and all the chaos afterward. If you don't like it, mark your master branches as unprotected. However, there's clear reasons for the current defaults.
If you try to do that too hard you run into the task automation problem:
In other words, "make the computer do things for me" as a diminishing returns problem. This is what you don't get.
What works best is a user-tool co-evolution. If I'm not mistaken, this is one of the core ideas of the Agile manifesto.
“We become what we behold. We shape our tools, and thereafter our tools shape us.” Marshall McLuhan
Git (the software) consists of two things. the git client (on your machine) and the git server (wherever you push).
It is most definitely not a GitHub problem if you pushed your changes to a local network git server, for example.
Git was primarily adopted because it solved those issues which were important ones at the time, people discovering git needed those tools and when discovering git would naturally come across and understand the trade-offs. IE: "I can't easily undo a change once it's on someone else's machine, instead I would need to issue a new change reverting it. But that's ok, because it means I can do as I like on my machine without screwing up the history for other people and only send a patch of specific changes when I'm ready."
The issue people now face is git has become so popular, because of those initial reasons, and we're dealing with a new set of problems which git never cared about.
"Project X is in a git repository, and I want to contribute a change".
This is a fundamentally different problem to the original problems git tried to solve. We're now in this weird space where most people using git are only using it because: it's what they already know, or the project they want to work on already uses git.
Requests like "I just pushed a change and didn't really want to" don't make much sense and don't matter much in the original use cases. Now many git projects use centralised hosting and a lot of people don't really care about git, just getting their work done, we now have this UX issue. The UX issue isn't a result of poor design or implementation in git, it's due to the motivations of users being fundamentally different now.
Sure you could argue that git should change or be easier, but then it would stop serving the original purpose. If people want a centralised source control with the ability to easily retract changes and have branches be the same across all nodes then really they just don't need what Git sets out to solve.
The issue is git is now dominant, and that forces people to use it even if they don't have the problems that git is really attempting to solve. That means they're stuck in a place of using a tool so they can collaborate, without getting any of the benefits of it. That's enough to drive anyone insane! It's like pushing a boat across land to get to another village when a boat is really to get to another continent, but no one makes cars because everyone's already boats.
We don't need "better" UX for git, we just need people to know about all the options, and part of that may include encouraging some people to choose more centralised options when it's a better fit for them.
Whether you realize it or not, that's gatekeeping. The point of UX is to remove artificial gates. When people apologize for the gates instead of fixing them, well... That's tantamount to threatening people's livelihood. It's a lot easier to do that when you don't think of it that way, and it probably shouldn't be easy. "I understand it, you shouldn't work here if you don't" is literally, "Fuck you, I got mine," with different words.
> about git being hard. But there is a shortage of effective, popular competitors
There is only so much oxygen in a room. There is not space for a million solutions to every problem, and once the Hype Train has left the station all you have left is to make the fiction true, or try to accelerate the Trough of Disillusionment so we can get on with fixing the problems instead of deflecting.
And I say this as the only person on a large team fit to do anything approaching surgery on screwed up git repositories. There is frequently a degree of turf protection via "he's a bastard, but he's our bastard". No, he's just a bastard. I don't claim any responsibility, I just have to interact with him.
We have this already. It's called collaborative desktops over VNC ...
> the differentiator between "branches" is not "what computer does it reside on" but "who did it"
So you're into collaboration, but not on branches? I would have said branches related to specific units of functionality, streams of development or specific issues.
Definition of branches aside, this is the way old-style centralised VCS like CVS, Subversion actually work - and you can still use SVN if you want to ... or you can use git in that manner and never have to worry about it's more complex details.
The whole point of Git is that it addresses the specific problem that once you are disconnected you de facto have a branch. Once you push to remote its more like that ideal you're reaching for.
> at this point it's not git anymore, so we might as well start from scratch.
I'm sorry this is really quite hilarious. Go! Stop whinging and go do it!
> We have this already. It's called collaborative desktops over VNC ...
We still want a revision control system, things like commits and all.
> So you're into collaboration, but not on branches? I would have said branches related to specific units of functionality, streams of development or specific issues.
Depends on the workflow. Many people have long-lived branches, introducing big features/refactorings. Many other prefer short-lived branches, where one branch typically is used by a single person. I still think branches should be focused on topics, but the topic (and thus the branch) must be the same on all computers, instead of having one version locally, another one that is mapped to it but potentially has different content on the server, and 1 different branch per other user. How many times have we had to "oh you pushed on your branch, I have to get it first"
> Definition of branches aside, this is the way old-style centralised VCS like CVS, Subversion actually work - and you can still use SVN if you want to ... or you can use git in that manner and never have to worry about it's more complex details.
Yep, that's the model: one place where people synchronize. The issue with those was not the centralization (look at GitHub), it was the lock mechanism. I can use git to replicate it, or I can use the folder.bak and folder.v1.final on a NAS method. It's not because it's possible that it's desirable
> I'm sorry this is really quite hilarious. Go! Stop whinging and go do it!
Ah, so it's not possible to criticize work until we have developed a complete alternative ?
Now it seems as though you’ve got a few moaners who have basically decided that this amazing and free technology isn’t good enough and they can imagine what they want but wouldn’t even begin to know where to begin implementing it.
If you can’t use Git, it’s probably not for you. Other alternatives do exist but they will never match git for features or community activity.
Most of what these people want could be achieved as you suggest, with a simple NFS share and system of folder numbering. Once you go away from the domain of text based code Git becomes a bit pointless ...
Github is a parasite.
> the quality of the tech that is Git is a testament to GitHub being able to make it this far in the tech space
But in reality, Github makes Git more complex, because now you have to understand the concept of forks. Not only is there your local copy and an origin, there is a 3rd repository in play.
I'm having trouble coming up with many that would be compelling enough to make that change, especially once you consider bad-faith actors in there (eg, I can't flood your git repo with my nonsense, because my code doesn't exist in your repository until the PR is merged)
I spend too much time doing archaeology to support squashed PRs, which eliminates a few alternatives I might otherwise suggest.
I believe this is how most Git repos are managed within organizations. I'm not sure why public repos need to require users to fork things to propose changes.
And isn't this basically how Github works internally anyways? (eg https://news.ycombinator.com/item?id=24882921)
We're trying to assemble this from different pieces, without a clear idea if we can even get there from here, given all of the roadblocks Information and other Theories throw in the way.
I hope someday we meet in the middle with systems that can handle code and incidentally a bunch of other problem domains we also care about.
— Isaac Wolkerstorfer
But the first impression is strong, it's still a good joke.
We have files, which are inert objects and form a "file space". We have diffs. Diffs can "act" on a file to produce a new file or a conflict --- we call this as "applying a patch". Mathematicians would call it a "group(oid) action". Diffs are a groupoid because (1) there's an identity diff that does nothing, (2) diffs can be smashed together, (3) if the smashing of diffs succeeds, the operation of concatenation is associative, (4) all diffs are invertible. If we were to delete added lines and add the deleted lines, this inverts the diff.
Finally, we have a rooted DAG where each node is a diff, and the root is the empty diff. Git queries enable to manipulate paths in the DAG, which corresponds to smashing together diffs along a path to produce a file.
If one groks this, the rest of git is a pretty poor interface on top of this nice mathematical structure.
For more physics-y applications of torsors, check out the baez article: https://math.ucr.edu/home/baez/torsors.html
What do you think is the difference between a "commit" and a "diff"?
> You have two nearly identical 22K objects on your disk (each compressed to approximately 7K). Wouldn’t it be nice if Git could store one of them in full but then the second object only as the delta between it and the first?
> It turns out that it can. The initial format in which Git saves objects on disk is called a “loose” object format. However, occasionally Git packs up several of these objects into a single binary file called a “packfile” in order to save space and be more efficient. Git does this if you have too many loose objects around, if you run the git gc command manually, or if you push to a remote server.
> When Git packs objects, it looks for files that are named and sized similarly, and stores just the deltas from one version of the file to the next. You can look into the packfile and see what Git did to save space.
If a commit references a "blob", and the "blob" that it references is, in fact, a diff, why would we say that the commit "does not reference a diff"?
There're optimizations on the storage level, compression etc, but on logic level those are transparent
The "diff" you're referring to is an implementation detail of the compression. It's not even always there; it depends on which commits are present in your clone. It's also not even the same "diff" you work with when you use git to generate or apply patches. Using the same word only leads to confusion.
There is a disconnect somewhere. The linked answer says:
> Now, git is different. Git stores references to complete blobs and this means that with git, only one commit is sufficient to recreate the codebase at that point in time. Git does not need to look up information from past revisions to create a snapshot.
> So if that is the case, then where does the delta compression that git uses come in?
> Well, it is nothing but a compression concept - there is no point storing the same information twice, if only a tiny amount has changed. Therefore, represent what has changed, but store a reference to it, so that the commit that it belongs to, which is in effect a tree of references, can still be re-created without looking at past commits.
You can recreate a file that is stored as a root blob plus some series of diffs without looking at information from past commits. But you can't recreate it without doing the diffs! You have to look at the root blob. This is, internally, tracked separately from the commit which created it. But your conclusion:
> when you checkout stuff, git doesn't do diffs to give you the working directory at that point.
cannot be true. If the working directory at that point corresponds to a blob which has only diff information stored, git must apply that diff to a separate blob in order to give you the working directory.
But when you create a new commit, that commit object is stored as a loose object, with any new file blobs and tree objects. This represents a complete snapshot of your working tree.
But git does not need to make a complete copy of the working tree on each commit. Because objects are referred to by the hash of their contents (with a git specific header), git only needs to store each version of a file once.
Another way to think of it, if it was diffs, if you had 1000 commits, getting to the 'head' would take forever because it had to replay all the commits diffs just to get there.
Yes, you could combine diffs & snapshots, but that in itself is a tricky complexity in an already very complex system.
[0] https://tom.preston-werner.com/2009/05/19/the-git-parable.ht...
There is also the obvious performance problem that you would have to replay all diffs to get to switch between commits.
Yes, it does.
> Every commit that deletes the whitespace from an otherwise empty line in a 30KB file is another 30KB of hard drive space
Yes, it is.
"It's worth repeating that git stores every revision of an object separately in the database, addressed by the SHA checksum of its contents. There is no obvious connection between two versions of a file; that connection is made by following the commit objects and looking at what objects were contained in the relevant trees. Git might thus be expected to consume a fair amount of disk space; unlike many source code management systems, it stores whole files, rather than the differences between revisions. It is, however, quite fast, and disk space is considered to be cheap." -- https://lwn.net/Articles/131657/
One of the insights of the git design was that, nowadays, disk space is cheap. The first releases of git always stored each object separately in its own file in the object database. Git still does so nowadays, but once the number of files gets over a certain threshold, newer releases of git run an "automatic GC" which combines these "loose objects" into a "pack file"; and within that "pack file", it uses a binary diff (a xdelta) between similar objects to reduce the total size. But that's just a physical storage optimization; in the logical model, whenever you ask for an object, you always get its full contents, not a delta against some other object.
Isn't it the case then that git doesn't store in full every version of a tracked file?
The question was does git's implementation store - in full - every version of a tracked file? The answer is that it doesn't. git has a sophisticated storage engine precisely to avoid the inefficiencies of the naive approach.
Ie. I can develop a fix for a issue for version 1.2.30 of some software, generate a the diff using the diff tool and then apply this diff using the patch tool to version 1.1.15 of the software. This might fail (or result in something undesired), but there no principal problem in moving the diff around and applying it somewhere else.
A git commit however is a particular version, so git is not really good at applying a commit somewhere else.
That only one is how it's implemented is besides the point really, until you get _quite_ low level.
I really hope something like pijul takes off.
In algebraic geometry, given a smooth algebraic group G, a G-torsor or a principal G-bundle P over a scheme X is a scheme (or even algebraic space) with an action of G that is locally trivial in the given Grothendieck topology in the sense that the base change Y × X P {\displaystyle Y\times _{X}P} Y\times _{X}P along "some" covering map Y → X {\displaystyle Y\to X} Y\to X is the trivial torsor Y × G → Y {\displaystyle Y\times G\to Y} Y\times G\to Y (G acts only on the second factor).[1] Equivalently, a G-torsor P on X is a principal homogeneous space for the group scheme G X = X × G {\displaystyle G_{X}=X\times G} G_{X}=X\times G (i.e., G X {\displaystyle G_{X}} G_{X} acts simply transitively on P {\displaystyle P} P.)
Look, there's even links to the sub-terms:
("algebraic group" article): In algebraic geometry, an algebraic group (or group variety) is a group that is an algebraic variety, such that the multiplication and inversion operations are given by regular maps on the variety.
("action" article): In algebraic geometry, an action of a group scheme is a generalization of a group action to a group scheme. Precisely, given a group S-scheme G, a left action of G on an S-scheme X is an S-morphism
("principal homogeneous space" article): In mathematics, a principal homogeneous space,[1] or torsor, for a group G is a homogeneous space X for G in which the stabilizer subgroup of every point is trivial. Equivalently, a principal homogeneous space for a group G is a non-empty set X on which G acts freely and transitively (meaning that, for any x, y in X, there exists a unique g in G such that x·g = y, where · denotes the (right) action of G on X). An analogous definition holds in other categories, where, for example,
Really, all you have to do is read the article carefully and follow the links to unknown terminology if you can't immediately intuit its meaning. However, it's only just basic category theory, really.
(yes, guys, /s).
- You have a branch `master`.
- You have a branch `feature` which contains commit C, which conflicts with `master`.
- You merge `feature` into `master`, fixing conflicts.
- You log the commits of `master`.
* First is the merge commit, whose diff contains code added by commit C (including the conflict resolution).
* Next you see commit C, whose diff contains code added by commit C (obviously)
Wait, how can 2 commits in a row have a diff that modifies the code in the same way? Well, mind you, the diff of a commit doesn't correspond to the moment the patch of the commit was added to the current branch, it only corresponds to the moment it was added to its own branch.Well why didn't you just say so!
But isn't the core idea of Git, everyone has their own repository and they share branches, kind of complicated and tricky? In my experience the developers I see having problems with Git are having trouble with the hard stuff, not the easy bits like committing and pushing a change.
Git's--and Mercurial's--secret sauce is the directed acyclic graph of commits.
Everything else is window dressing. It's complicated if you're used to a linear sequence of commits, but it's not too hard once you grasp the tree structure.
All operations are operations that manipulate (or share) the DAG, so it now becomes a matter of mapping how you want to manipulate the DAG onto the command set the tool gives you.
Git's toolset was designed by a dozen madmen that didn't talk to each other, so it's a loosely connected set of tools with conflicting syntax and meaning. Mercurial's toolset was designed to be used, so if you know the right terminology, you can easily figure out what command to write. Want to commit something? It's probably hg commit. Want to rebase? It's probably hg rebase. Etc.
Git exposes unnecessary complexity. But it won the DVCS popularity contest, so we're stuck with it. I wish something else had won. Oh well...
That being said, I know there are some who have trouble with Git. But IMO it isn't because Git is hard, but because they don't have to truly understand Git to use it. That's how easy it is.
I think this is the crucial part. Git will come off as difficult and strange if you're used to using a centralized VCS, and expect Git to work like it. But that isn't really indicative of Git's own complexity, just its differentness.
I can use git all right but the fact that I need about 20 different commands to do my job, 95% of them with extra parameters and almost all of them with names that don't reflect what I want to do from a functional point of view is utterly dumb. Again, functional! not technical! The UI should reflect end user functionality, not internal technical details.
edit: on second thought no it's really not very coherent. If you exclude <files> it means checkout all files if you write a <branch>, but no files if you write no <branch>. So excluding <branch> doesn't consistently do the same as using <current branch>. I guess git does kind of suck.
git restore filename
https://stevelosh.com/blog/2009/08/a-guide-to-branching-in-m...
Simple.
The deeper explanation doesn't mean more complex system.
But the moment I could import SVN to git I immediately switched to Git for everything. And Mercurial... I guess it's a matter of preference, but I personally never got the hang of it. And the fact that they had both SVN style continuous IDs AND hashes was deeply confusing to me.
The only thing I did find confusing in the beginning was a) the distinction between pull and fetch. b) getting used to the fact that I don't really care about continuous IDs (or hashes for the most part ) and think more about commits relative to where I currently am.
In addition to that things such as `git add -p` or `tig` are so much more convenient compared to other VCS CLIs. But even if CLI isn't what you want we're now a couple years beyond having beautiful third party Git GUIs
The reason I want to stick to the basics is because of one interesting thing I've noticed: a lot of engineers sincerely believe that they are git experts when they are nowhere close. And until I locked down the GitHub repo with admin privileges, that was a dangerous thing. So I'm trying to work a system where no one in a team where not everyone is truly expert at git only uses the basic commandset from git.
One thing I can say again to emphasize - git maybe the simplest Vcs you've used, but it's not a simple tool, and its most definitely not intuitive for everyone. If it is for you, that's great, but maybe there's a lesson here about how not everyone's brains are wired the same.
Once, when leaving a job, I decided to copy all of my local WIP branches to the server.
I whipped out this fancy --mirror option I had just heard of:
git push --mirror $remote
Surprise! All branches on the remote repo got wiped. My local refs replaced the refs on the remote.Somehow I found the right commits floating around in the git ether. I was able to recreate the branches, but I had to recreate their names by reading the commit log.
Did I mention this happened on my way out the door from a job? In retrospect, I shouldn't have panicked so much -- there were daily backups -- but the sheer terror I felt has made me read the man pages really closely to this day.
Something like
You are trying to remove commits from twelve branches.
Are you sure that's what you want to do?
Include the --force option to go ahead with this change.
would be a whole lot better.Even if it gives you the tools to undo the mistakes, it saves you time and stress if it keeps you from making the mistakes in the first place.
"...locally updated refs will be force updated on the remote end, and deleted refs will be removed from the remote end..."
If you just want to push all branches or tags you should use --all or --tags.
but if you want a system that protects you from these mistakes by making mistakes impossible, then you get a system that is very rigit and actually harder to use.
git protects you from these mistakes by making it possible to recover.
in this particular instance though, there could probably be some extra help to recover. (some way restore the removed refs)
To be fair, one should always look up options you are unfamiliar with before using - and Stack Exchange is not an authoritative source.
--mirror
...Newly created local refs will be pushed to the remote end, locally updated refs will be force updated on the remote end, and deleted refs will be removed from the remote end... [my emphasis.]
On the other hand, if you are on a system where the behavior can be fundamentally altered by multiple configuration options, this will not necessarily help you much.
...This is the default if the configuration option remote.<remote>.mirror is set.
It is also a very wholesome and meditative activity.
Most piano players don't have a clue about how to tune their pianos, though.
Most professional musicians know their instrument very well - and still know a man for the "hard" stuff, e.g. for thorough maintenance or repairs that require craftsmanship.
And there are obviously variants. The guys that fix their instruments regularly and experiment with e.g. cooking your stings, and musicians that hand them in for the tiniest, easiest tasks.
Git ends in my production multiple times.
1. In my side project game, auto update and replay system is based on Git. For every update, there will be a commit appended to the code repo which is the most recent update. If a player wants to replay a game in previous version, just checkout the appropriate commit, and run the replay using exact the same code. I'm freed from backward compatibility issue & update subsystem which handles diffing, compression, transporting by a single decision. https://github.com/feisuzhu/thbattle/blob/master/src/autoupd...
2. Another project written by me, which is a monitoring system, distributes it's rules by a git repo. Monitoring agents in the nodes cares about authenticity of distributed rules. So I just sign the tree hash and embed the signature in commit message, which will be later validated by monitoring agents. https://github.com/leancloud/satori/blob/master/satori-rules...
Once you are collaborating, there is simply more to good code than what you our your peers know about the code or the language. Working well and effective with others has a huge impact on you, your peers, the "company" and in the end the product.
Further, I know a lot more about my cars than just how to change the tires. E.g. there are know issues with certain popular car models. Knowing about them does help, not every random mechanic does.
Also, if my car does certain things (surprise, they do all the time, they are complex nowadays) that are easily explainable or even somewhere in the manual, I am not going to ask for help every.single.time. I have stuff to do, be somewhere. I am not going to put my car in the dealership all the time.
Git for me is a productivity tool, in particular when I'm working with others.
You sound like the guy I once collaborated with that didn't want to use git (because why should he learn it now?) and instead sending the whole code via skype every day.
You're annoyed at them... because they do things that you don't know how to do? How is that their fault?
"In the end git is not in production, it's just a tool to manage code, I'd rather be an expert on the code than the coding tool."
That's a very short-sighted attitude. It's like saying, "I don't want to learn how to operate a bulldozer, because I'd rather be an expert on dirt rather than the tools to move dirt."
That's exactly what I'd expect someone to do after I commented on their PR.
> That's exactly what I'd expect someone to do after I commented on their PR.
The vast majority of people do not. I certainly wouldn't expect someone to waste time on that.
That's a very bold claim.
It's certainly been the expected workflow everywhere I've worked. You might consider it a waste of time but I'd wager the resulting mess of commits from not doing so wastes far more time in the long run.
An unclean history is less likely to work well with bisect too, as the individual commits may be broken.
You mean when where and how a change was introduced? I dont think bugs are located in the history, since bugs are operational failures on a deployed branch.
1) argue that they really don't need to change anything 2) push more commit(s)
Why would it be better to rewrite history?
So there's little point reading about exotic features upfront other than to know they exist. And which features are exotic depends on your workflow.
It would help if git interface was consistent enough to make remembering this stuff easier.
For example I never remember the exact options for git reset because I'm using it just rarely enough to forget them when I need them again.
And as a side bonus it will probably make you a better coder.
I would argue the value is in knowing that something is possible using the `git reset` command so you know to go looking for the exact option to do what you want. And more likely you'll remember the operation if it's one you find yourself using frequently.
-- someone or someone else. I forgot.
This is both good and bad. I get a lot done, but not always as efficiently as possible, and I do find myself realizing, down the road, that I didn’t need to do it that way.
But it’s entirely possible to get caught in “tool rabbitholes,” where the main goal becomes subservient to the infrastructure.
I remember dealing with folks that would spend three days, writing CLI tools that saved, maybe two hours, over the course of a year.
Her problem is she gets discouraged halfway through and never gets to use the stuff she learned.
My problem is I got good at winging it and looking up stuff as needed so I never learn the stuff I didn't needed even when it could be useful if I knew about it.
Probably some compromise would be the best - start with what you need and force yourself to go deep into one random topic each month.
> I remember dealing with folks that would spend three days, writing CLI tools that saved, maybe two hours, over the course of a year.
My friend is like that, but I learnt to aprecciate this when I worked with him. The script maybe only saved 1 minute of work 10 times a year, but more importantly it's self-checking documentation of how we are doing stuff we rarely do.
This means it isn't hard. If you are capable of understanding algorithms of any complexity you should be able to learn how to use git (and how much of it) without treading on ground that is dangerous for you to use. All of this "it's too hard" rhetoric is infantilising or coddling people who frankly shouldn't be trusted to code anything of importance anyway. There's no shame in admitting your own limitations, but there is definitely shame in lowering the bar for others so much you are actively harming the industry.
Besides, nobody is arguing git needs to be made weaker, just that it would be nice if it had a more gradual learning curve. Easy things easy, hard things possible. If you can’t see how git is hard you’ve forgotten what it is like to be a beginner.
Software development is hard. That's why we have to spend years studying it and earn conspicuously good wages.
A basic project doesn't need git anyway.
Agree on the need for education to be a good developer though.
We have the whole education system to deal with that. It's the same problem as in mechanics, chemistry, biology, etc.
If you intuitively grok how git works, that’s great. I’m going to guess you probably don’t really use it in any challenging or new situations and are just comfortable with your particular workflow. But maybe you do have that mastery level over this one tool in your code management system.
But guess what, other folks, true genius folks, either can’t or don’t have the mental bandwidth to learn every nook and cranny of this tool. If you don’t recognize that, you are willfully dismissing a lot of really smart people because their brains don’t work the same way yours does. But when you do that you are weakening yourself and your own capabilities.
So step back and re-assess your take here. It’s wrong, and it’s toxic to your own outlook as well as those around you.
I don't hugely feel like seeing things from your point of view because the only thing you've really told me that might change my mind is that you lose people when you require a basic amount of capability. I'm sorry to hear that this grievously wounds you on an emotional level, but I don't see that as a loss.
Saying "basic competence" is horrifically abusing language here. Git is a glorified save/share/undo tool, demanding people spend several days reading the manual is an absolute caricature and yet you're seriously saying that.
The reason people are mad at you is that people have lived experience of the interface sucking and failing to do the job an interface does - convey via context what it does and you're basically blaming them for wanting to fix the problem they've experienced instead of sucking it up and Being A Real Man and solving problems they don't have as a workaround for the tool failing to solve problems they do have.
And it's not like Git's interface problems are subtle. It's an absolute joke, and you're not even claiming it's an acceptable interface so much as rejecting the entire concept of user interfaces at all. I'm not sure how to explain how utterly infuriating that is.
You're saying "you're doing it wrong, so I don't care" while simultaneously complaining that some of the solutions could hurt other peoples' use-cases.
What is the correct response here? Reject their own memories and emotions and yield to your blame, or call you a willfully-oblivious fuckhead?
All that being said, this is not a reason to then take the next step and claim that basic competence in what is today an essential tool is optional. It is necessary and to work well you must know it well, otherwise the frustration you point out will be part of your life every day. As opposed to something that you live through and say goodbye to.
The fact that everyone is taking this as toxic or willfully oblivious is as far as I'm concerned infantile. It has nothing to do with "being a real man" (whatever that means to you), it has something to do with having the maturity to realise that you are making your own problems.
That is not to say we cannot build a better tool. Perhaps we can! Up until this point I have not seen it done without losing something else in turn.
One of the reasons that we able to achieve so much with computers is that there is a separation of concerns between different areas.
Requiring everyone to fully understand git is like requiring people who code in high-level languages to understand and apply chip design in their day-to-day work.
Imagine if when you tested some Python or Java code you got an error from your CPU and needed to take it out and debug it with an electron microscope.
Contemporary git has this disease. Its (command line) user interface is a mess. I could say more about what you would do to make a better version but a comment isn't the place for that.
The defence that you are using - that smart people should be able to learn git fully - is like saying that any and every smart programmer should learn IC design and buy their own electron microscope, and that's why it's OK that the chips keep breaking.
I'd be very interested because it's rare for me to see anyone attempt and, when I do, they break a basic use case.
Insanely complicated commands to undo things are one symptom of this.
As a user, you want to "save" some code and you also want to "share" it with others. You also want a historical record of what you did.
But obviously you will occasionally save and share things you didn't mean to. Like your Python virtual environment, like a bunch of pictures in their binary format, etc.
A sane version control would provide a point-and-click way to make these disappear from history (though with adequate security protections to make sure that only authorized people can do it).
If I'm a user and I want to save, I do it with my text editor. If I want to share, I can do it with Github, Gerrit, Gitlab, email, pigeon.
I never email people things I didn't mean to and, if I did, I wouldn't expect my email software to let me delete it. The centralised services allow it to some degree but even they don't allow information to be un-disseminated.
VCS is necessary to deal with changes that overlap and conflict. It's not for backup and it's not a method of communication. If all you need to do is save and share, you don't need VCS.
So nothing is really gained but not allowing this, but it makes git very user-hostile because mistakes cannot easily be undone.
By removing it's decentralised nature you've fundamentally built a different VCS. Perhaps SVN is acceptable for your use case, that's great! It's definitely not git though - basic expected use cases were lost as predicted at the start of this thread.
The core task of a VCS is versioning and collaborating on text of some kind. Git doesn't do this in an optimal way, so eventually it will get replaced by something better. In the meantime we'll all get on with learning its ins and outs, just like previous generations learned how to use punchcards.
git rebase -i {hash before your changes}
git push -f
And since you talked about point and click, you could easily enough use github permissions on branches to prevent this on protected branches or you could configure your git repo to disallow force pushes. To get specific branch protections on a normal git repo you would need to use a hook to validate the update before it's accepted.For example, suppose I init a new repo and accidentally commit my entire virtual environment, then push, then do some real work, push a few times more and then a colleague notices (after they have pulled, worked on and pushed) that the venv stuff is there.
In an ideal VCS, you would have a simple command like git purge /badfolder that would make it as if it never existed.
But AFAIK that doesn't exist, or at least the ways to accomplish that are pretty gnarly and dangerous.
Second, I would tell you that git has a command for just your situation.
git filter-branch
https://git-scm.com/docs/git-filter-branchYou can run a command against every commit and it will then recommit. That would let you remove, for instance, an entire subdirectory. The downside here being that you are rewriting history on something you've shared with the world and that has larger potentials for causing issues with contributors.
I guess my point is really this, git is simply one of the many tools you likely have to use on a daily basis. If you have to use a tool in your daily job it's in your interest to really grok the various ways your tool can be used. You'll want to really understand the primary use cases in detail and the less used ones you'll want to know in passing at least. That allows you to realize that something is possible with the tool, even if you don't recall the exact specifics. A machinist would have the Machinery's Handbook, a programmer will have multiple internet references. Maybe the real point is that it's _ok_ to not know the exact syntax and need to reference it for more esoteric operations.
Git demanding a large chuck of user mindspace isn't an advantage for git, it's a signal that git is bad and needs replacing.
The ideal option for each of these things is that it "just works". When you have to think about the internals of your package manager or your CI or your virtual environment, that's a flaw in it, not a reason to celebrate.
I picked Debian over Red Hat since, at the time, I could understand how .deb packages worked, and look over the state of the system. Red Hat had more opaque internals. If something broke on a Debian system, rare as it was, I could go in and fix it manually. If something broke on a Red Hat system, it was generally in a binary database file, and meant a reinstall. Red Hat also broke more often, I think for very similar reasons in design philosophy.
If I were making a tool for grandma to manage her photos, that's be something different. If you're making a coding tool for 3rd graders, perhaps you want to hide more stuff too, but even there, many modern coding environments translate blockly into Python/JS/etc. code, and show the code to kids so they can see under the hood.
I have a car, and as a car user, I want thinks to just work. As a car mechanic, I'd like things to be understandable, fixable, documented, and transparent.
git is like that. It has simple internals. Once you understand them, the userspace become very understandable too. The upsides of the elegant internals far outweigh the downside of a slightly clumsy userspace, which is why it's the dominant VCS right now.
It took over precisely from things which "just worked" with a simple userspace, and clumsy internals, like SVN and CVS.
I use PyCharm. I don't know how PyCharm works internally. I don't even know what language it is written in. I know that it provides syntax highlighting, smart replace, code completion, etc.
Similarly, my car mechanic has a bunch of tools that he doesn't understand in detail; they have interfaces (like a gauge on a pressure sensor).
Progress requires these interfaces, it requires these abstractions, and over time I'm pretty confident that we'll get a better VCS than git that has better, more user-friendly abstractions and it will take over the market.
You aren't writing x86 assembler. You are presumably writing some other, higher-level language. I would fully expect you to know that language in detail and even better to understand the performance implications of the choices you make in that language. Knowing the lower level details helps there, but it's not 100% required.
With git, it's something you _directly_ interact with so I would expect you to understand it in great detail.
Yes, you are describing what is broken about git: its abstractions are leaking too much so people who touch it have to know all its internals.
I touch x86 assembler every time I run high-level code, it's just that other kind folks have gone to a lot of effort to make it so that I don't have know how the internals of that low-level stuff work.
Abstractions allow people to be productive without knowing in great detail how absolutely everything in the universe works. A good tool has simple, non-leaky abstractions with a simple interface. Git is not a good tool.
1) It's like understanding the basics of databases, network protocols, or compilers. It gives a lot of insight to how things work in a pretty deep and generalizable way. How do you organize data, and why are DAGs, Merkle trees, and hashes awesome? It's a beautiful case study in data engineering.
2) It's like knowing the shortcuts in your editor. It makes you more productive. If a programmer is hunt-and-pecking to type, and gets confused by shortcut keys, they'll be less productive.
Yes, I understand not all programmers will know how important it is to know this stuff, and I won't disadvantage someone who hasn't done this YET in hiring. But I would never hire the type of programmer who says "I don't need to know this." You do.
I'm sorry, but it takes a couple weekends of work to write yourself a git end-to-end from scratch. That's 0.5% of the time you put into a CS degree. If you don't have the interest, discipline, or drive to do that, there are plenty of jobs out there.
git internals are simple, but hard. Like Go. If you don't understand them, the userspace is a near-infinite pile or arcane complexity, incantations, half of which break something in counter-intuitive ways. If you do, it's a matter looking up the right command in the docs in a few minutes.
Yes, compilers, database, and other tools abstract away a lot of stuff. But if you don't understand the internals, you're likely to hurt yourself and my system in very bad ways. I don't want that on my team. My experience is good programmers are fluent one or two abstractions up and down, to not e.g. make a database query that does a full table walk, run out of stack space with a compiler that doesn't do tail recursion (and conversely, know they can use tail recursion with ones that do), etc. A tool you use every day definitely falls into the category of Stuff You Ought to Know, in a way that understanding how quantum tunneling is used in an SSD is in the category of Stuff You Don't Need to Know.
If you're hurting yourself with git, that's a good signal it's in the Stuff to Know category. And if you've wasted more than a few hours fighting git, as it sounds you have, it sounds like making a focused effort to learn it will save you time in the long term. Probably in a few months, even.
I use an SSD every day though, as well as an LCD display and a laser in my mouse. So by this reasoning, I need to study quantum mechanics; it would only take a few weekends of focused study to understand the Schrodinger Equation etc.
These things fall into the "Don't need to know" category because we as a species have made very effective user interfaces to them whereby you really need to know almost nothing about their internals to use them.
The ideal version control system would work like a mouse or a monitor. Completely intuitive, just works™.
As a footnote, I would expect you to be able to understand things like SSD performance and reliability, and how it's affected by complex algorithms in the drive controller (e.g. wear leveling, garbage collection, write block size, etc.). I would also expect you to be able to understand things like how subpixel rendering works, how rendering engines coordinate within LCD refresh, or how displays advertise their parameters to computers.
You shouldn't take those as black boxes either. You do get into bugs and issues which relate there, and an experienced software engineer will have a depth of knowledge around oddball topics like that. That brings huge value.
It sounds like you're not a nerd. Why did you go into software engineering? It sounds like you're not interested in the stuff. There are lots of career tracks which don't expect people to do those sorts of deep dives, and where willful ignorance is okay. Engineering, including software engineering, just doesn't happen to be one of them. All the good software engineers I know will do dives into this stuff, and that expertise accumulates over time.
The key thing is most of us enjoy those deep dives. That's what makes the career track a good fit.
If you don't, you'll be doing the equivalent of maintaining a COBOL database on a mainframe as you get older.
For my engineers, I'm not looking for tools which are "Completely intuitive, just works™." That's Scratch. I'd advise you to code in Scratch if that's what you want. I want tools which enable people to be productive, efficient, and get stuff done at a high level of quality. If that has a learning curve, that's okay. People are coding 40 hours per week. If my programmers spend a month learning each year, and that makes them 50% more productive, they'll beat your Scratch team. That's why good programmers get paid the big bucks, and mediocre programmers can't find jobs.
There are two separate issue here though.
(A) How much work does a given person want to put in
(B) How much work does a given tool require.
It can simultaneously be the case that git is bad/overcomplicated AND that you should only hire people who bother to learn it really well.
Why?
Well, learning hard things is a reliable signal of diligence and hard work, which are generally useful traits.
But at the same time, forcing everyone to learn something annoying and time-consuming just as a test of grit isn't maximally efficient. The same effort could be put into more productive tasks.
> Why did you go into software engineering?
Well, I'm not a software engineer - in the Data/ML area so I am much more interested in the properties of data than the properties of code. But having said that I certainly like clean, efficient code and I care about languages (maybe just spoiled by python?!).
I can't see myself as a software engineer so I think your instinct is right. My passion is data and ML.
For a data/ML position, in most cases, I'd expect you to be able to handle data cleanly and efficiently.
If you can't, there are jobs far over on the data side, but:
1) As a business data analyst, you're fine with Excel and PPT, but you'll be paid roughly 1/3 of an ML/SWE position, and you should have excellent communication skills.
2) There are primary mathematical positions, where you work with a data engineer, but you'd better be awesome at math. AND it still helps to be able to handle data cleanly.
Even so, good data workflows require knowing what you did, when, and to which version of data. Properly used, git provides an archival log of some of that. I use very similar data structures when I build some of my own data pipelines too, with data stored under its hashes, Merkle trees, DAGs, and similar. If you find that "annoying and time-consuming," I'd hire you for a business data analyst, and not much more.
It sounds like you find that stuff boring, though. It's a test of interest, passion, and drive, much more so than diligence and grit. Although those are important too.
Merkle trees are also fun and have applications elsewhere like cryptocurrency/blockchain.
I don't have a problem with computer science in general, it's a fascinating subject.
These commands will get you 99% of the way:
- git status
- git branch
- git pull
- git add
- git commit
- git diff
- git merge
- git push
- git checkout
For everything else there's StackOverflow, but the info in there comes with the risk of being stale.
--------------
Edit commit abaeb3b4: Add missing commands and improve formatting
Edit commit 842babda: Add git checkout
And to give yourself a sense of the commit graph, these aliases come in handy
[alias]
lol = log --graph --decorate --pretty=oneline --abbrev-commit
lola = log --graph --date=short --pretty=format:'%C(auto)%h %C(dim)%ad%C(auto)%d %s' --all
The only 'advanced' thing I commonly do is `git rebase -i` to squash a bunch of WIP commits. And a shell script I have to turn merged branch into a tag, and remove the branch.The other day I had to remove a sensitive file that accidentally got checked into the repo for a couple of commits behind HEAD, and was glad that git had the power to do this in one line and without fuss. (Edit: but yes, I had to look it up on SE)
I've honestly ever felt the need, or had the requirement, to look at the graph.
Most people can get going with those 99% commands quite quickly, the problem with git is any move from the known path creates some pretty amazingly complicated scenarios.
And those '1% of the time' commands blow up into time-consuming rabbit holes of complexity. Often, Stack Exchange has several answers for the same question, highlighting just how much inherent complexity there is in the product.
Managing software versions across repo can be a very, very complicated problem. Git provides you with a pile of tools to do 'almost anything'.
A 'well designed product' would make the toolsets and concepts focus heavily on the 'main operations' and then have clear, clean rational idioms, practices and tools for the odd cases, and 'dangerous cases' wouldn't be allowed without some kind of special command.
They have the 'Golden Rule of Git' which is to not rebase on a public branch - this is an excellent example of poor product design. There should be no 'golden rule' that developers have to understand - it shouldn't be possible (without special admin commands). If branches are named/tagged and managed properly, the system would be smart enough to let you know you can't do that, and why.
Administrators exist for a reason, 'sudo' exists for a reason etc.
People who love powerful things, and have an inclination towards complexity seem to love git, people who have a product orientation see it differently.
Already that's a little bit complicated though.
Even though yes, this use case probably does exist, it might be a tricky thing to unwind for some people - what would they do when they have already changed the history of 'their' public branch (?) is something they'd have to carefully think about.
You can add to them and refactor patch series that are on them, equally valid in the eyes of git.
For example a development branch has no implied "promise" about stability of its history, it is much better to not only refactor the code but also refactor the history so sub-patches are squashed into the single feature patch that they logically belong to, and not spawn lives of their own. There is no reason to run that kind of development branch like a stable "branch of record".
And yet people do it all the time.
The 'rule' is easy enough to understand.
But it's not always clear 'why' that is (in many cases, it won't matter), or when exactly it applies.
In the lowest common denominator cases, the rule is not so hard to follow, but it can get messy quickly and there are many ways to break the rule.
It comes with the territory. We're dealing with tools borne into world where they are, more and more, expected to be suitable for any purpose. Tough mandate, and not the tools fault.
One day git will be supplanted with something that has a different set of issues. Progress.
Every single developer I work with (or have in the last 8 years) does this. "Messes up the history" ? The merge commit describes that there are uptaken changes from the "main" branch. It doesn't seem to be a problem in practice.
When we release to production, develop gets merged to master.
We consider a 'feature' a large piece of work that will take several weeks, during which time several releases to production may be done for other work/tickets.
Same goes I think for `git restore` over `git reset`.
That's a great summary for the majority of Git users. I am still motivating people to spend the time to learn it "properly" if they're using Git daily.
First of all, it will make them more efficient. I've seen too many people literally redoing their changes, because a cherry-pick/rebase is "an operation they don't understand".
Secondly, they will be able to solve most issues when (not if) they occur. Sure, I am more than happy to help my colleagues solving their issues. From "why are those changes in my PR" to "our Jenkins job went rogue and now we've got hundreds of MB of data in our repository that we would like to remove". But the time of me explaining things the "learning by doing" style would be better spent actually learning Git.
I still miss Mercurial. Unfortunately most people moved to Git so I also moved to it.
The Lemming Effect.
The git CLI tool isn't great either -- that's probably the hardest part of git.
I like to say that git is a "white box". You need to understand the internals to be able to use it.
Contrast this with "black boxes" where you don't have to or even can't understand what's going on.
Some would argue that software shouldn't be built that way, but I will respectfully disagree. It's not an end user facing consumer product, it's a tool for professionals. You wouldn't expect anyone to operate a table saw or a milling machine without some understanding of what's inside the machine.
I do agree that the git user interface is inconsistent and full of caveats. But as long as you understand it's just a directed acyclic graph of commits, you can dig yourself out of any hole you get into.
? Coming from a family of carpenters, I can assure you none of them really know that much at all about the internals of the table saw. Maybe a little bit.
The 'black box' analogy is upside down: there are a million artifacts of the computer that you use every day for which you have no understanding. We use encapsulated concepts to be able to leverage much more complexity than we would otherwise.
Having to deal with the 'inner workings' of git, is like having to have the instruction set for the chipset your computer is running on handy 'just in case'.
Git is very powerful, but very poorly designed from a product perspective, there was no 'strategy' just 'add commands and flags that do this and that'.
When products expose considerably more complexity than they need to for most uses cases, it's just bad design.
I also have a sneaking suspicion that so many 'git experts' are really just expert within a fairly narrow range of commands/options - because when I start to ask more detailed questions, the answers are never clear.
No other product has consistently caused so much confusion, wasted time. Though 95% of my personal interactions are fine, there are just too many times where we have Senior Developers, huddled on someone's machine, trying to solve some arcane problem - this is the 'not very hidden cost' of git.
I would say: "Within Git, there is a much smaller and clearer CVS struggling to get out."
Every carpenter I know knows how to change the blade, tighten the arbor, check the fence, adjust riving knives, clean away the dust, tension the belts (if applicable) and maybe even change the motor. And there isn't much more to a table saw.
Getting back to Git, I agree with your sentiment "Within Git, there is a much smaller and clearer CVS struggling to get out.". Most of us should strive to stay within the set of simple git operations.
However, then there's all the other corner cases that are sometimes applicable. Such as clearing away your accidentally published private keys using `git filter-branch`. Most of us will never need this, but it's there for a reason.
But if one groks the "DAG of commits" concept behind git, you can understand what filter-branch does and why and how. It's not a very complex concept.
Again, I won't defend the inconsistent user interface. It could be better. But even that can be understood when needed by looking at the documentation as long as the concept is clear.
I click on the file and click on "unstage". I don't know why people insist on using the command line for their dvcs. Is it even possible to selectively unstage or reset only a part of a file without a GUI?
I use both. More complicated stuff I usually do from the command line because I do them rarely enough, and I change IDEs often enough - that I just don't know how to do them in IDEs.
I used git regularly for last 6 years and in that time I've been using eclipse, netbeans, kdevelop, qtcreator, visual studio and intelliJ. And a few fringe IDEs as one-offs. I would have to remember 7 different paths in nested context menus for everything. I believe it's not "unstage" but "rollback" in IntelliJ, but I would have to check that in documentation before I do it anyway.
> Is it even possible to selectively unstage or reset only a part of a file without a GUI?
Sure - it's even faster than in gui, because you do it with keyboard only. I just can't remember the exact options.
And you don't have to remember the menus because they are contextual. Select a portion of text: unstage selected lines, reset selected lines, etc. Select a commit: checkout, create tag, revert, etc.
Things that are complicated on the CLI become routine and that changes the way you work.
It's also more powerful.
But the tradeoff is ugly within the context of the nature of the UI.
Git is like C++, it has a lot of features, the UI is not well thought out and it creates countless corner cases.
Git was not designed to focus on the core cases, making things simple.
Git is one of the great 'litmus tests' for product design thinkers. People who don't understand why git is problematic (even if they are really good at it) I think would have trouble with product design.
My explanation would be:
Git won because it was used for Linux and because it was fastest where it mattered.
A copy&paste of my previous comment:
Everybody's brain is different but I actually understand all of git's internals (the "plumbing") but it doesn't help me with the git CLI (the "porcelain").
Yes, I know that Git is a DAG (Directed Acyclic Graph), and that HEAD is a pointer, and the file format of BLOBs and SHAs, etc. If I were to implement a DVCS, I would inevitably end up reinventing many of the same technical architecture decisions that Linus came up with. But none of that insider knowledge really helps me remember git syntax if I haven't been using it in more than a month. Even though I grok git's mental model, I still can't answer the top-voted "git" questions on Stackoverflow without a cheat sheet: https://stackoverflow.com/questions/tagged/git?tab=Votes
The git UI and unintuitive syntax is just too hard for me to remember unless I use it every day.
Also to add.. the concept of "git index" as a staging area adds some complexity as well. Yes, there are good reasons for it (1) it lets one craft a specific subset instead of all changed files to commit and (2) it's a performance boost because a Big-O type O(n) loop runs faster when iterating through the staging index (small "n" of dozens) to detect changes instead of looping through the entire source code tree (large "n" of 10,000+ files in a big repo). But that flexibility adds an extra cognitive burden when a newbie just wants to save a "backup snapshot of the repo". For a newbie, the extra indirection layer of "staging index" seems superfluous and confusing. That's why some present an alternative porcelain to git that doesn't expose the staging concept: e.g. https://gitless.com/
(To clarify, I'm not recommending Gitless but just giving an example of why some felt motivated to simplify Git's porcelain.)
This was surprising to me, and shows how different people's experiences of git can be. My workplace switched to git from an obsolete centralized VCS earlier this year, and I could easily answer these.
Something like this is probably where the line between those in this thread who agree that git is too hard, and those who think the detractors are just lazy and stupid, runs. Folks, people are more different than you expect!
Maybe you find it easy because you don't see the subtleties. The answer to reverting the last commit for example can't really be that simple because it depends on what the user really wants to do. Do you want to keep the changes in staging? Reset the index but keep the changes in your working copy? Or reset the files to their state at the previous commit?
All sorts of workflows become substantially more difficult (if not impossible) with kitchen sink commits. Undoing a single-line change, for instance. I dislike large pull requests, let alone commits that introduce a half dozen different changes.
Sure, if you’re really disciplined you can produce small commits without staging, by committing as you go along, but you’re breaking flow every time you commit in this style.
I say all this because I would love a CLI that has half-way sane handling of (e.g.) restoring staged, deleted files; doesn’t conflate restoring files with switching branches; has consistency of flags between commands (such as commit vs stash message); etc., etc. I should try gitless ;)
No, I'd say the opposite. The staging area encourages me to think that I can make my change and split it up into logical commits afterwards, even though I know I'll actually just give up and make it a big commit. When I didn't know about the staging area and just committed whenever I could, I produced better, smaller commits.
That sounds like a personal discipline problem and not a poor tool.
Both are guns. Neither will shoot you if you understand how to handle it. One is much easier to make mistakes with than the other.
The parent is saying that Git is the Nambu of DVCS.
https://en.wikipedia.org/wiki/Type_94_Nambu_pistol#Unintenti...
Not for me. When using Mercurial back in the day I would manually split up commit, usually by copying over sets of files into a clean repo and committing there.
In Git tho the staging area is a lie. It encourages you commit half-truths. What I'd really want is to be able to enter a commit mode where the on-disk and staging area roles are flipped.
I want the stuff on disk to be what I commit, I want the "staging area" to be the changes that I've made that are not yet committed. This way I can pick a set of changes, compile, run tests and commit.
With Mercurial you could sorta do this with stashing I think, but I swore off it after losing changes a few times.
I wish git didn't use the disk at all! It gets in the way of parallelizing work. For instance, I'd love to be able to make a bunch of trial commits, then in parallel verify that none of them breaks the build. Or while a build/test loop is happening on one branch, switch to another to continue working.
https://github.com/tv42/staged does something like that by writing the staged content to a temp dir.
(It has some smarts for Go GOPATH adjusting on top, but might not do things right with modules, at this time.)
Once done delete temp branch and push.
Simple needs have simple answers.
git add .
git commit -am '2020-11-17'
Sure, you can ask "why are there two commands?", but this is not so much an issue of cognitive burden as of typing burden. If you only want one thing, you only have to know how to do one thing. If you don't want to know why the procedure does what it does, you don't have to.This is the mental model 99% of newbies will have for something that basically pledges to save and sync each version of your files.
Deviating from the user's mental model will create roadbumps and should not be done without a very strong rationale. Especially not for a feature that's fundamentally optional.
So? When you're saving a file, you're also overwriting its entire contents. Good luck reverting back to the file before you saved it.
There is no automatic model for "this change is worth tracking" and "this change is not important enough to annotate". That's the model that git is enabling, and it has nothing to do with the "save" button in an editor. If anything, it has more to do with the "track changes" feature in Word, but more powerful because it allows you to group multiple edits in the same change.
I don't understand the point you're trying to make; this is just as true of the command I gave.
zfs snapshot pool/home/git@2020-09-07For the questions, what's bad with quick help on SO? It's maybe less effective than reading the documentation that ships with git itself but for sure much more popular and less to read.
Git truly is a command-line utility, little known is that it ships with more than one gui in the base package out of the box. handling the staging area with git gui for example is straight forward unless you have more than 5000 unstaged files, then the gui informs you about it's limit and mass handling is far easier on the command-line anyway.
This sounds like you just don't use or need those things much, which is fine if it works for you. Of the top 10, I can answer 9 of them without doing any research because I've used these commands a lot and they've become a part of my workflow. The one I'm missing? I've never renamed a git branch. If I needed to, I'd probably just do git branch --help or google it and figure it out in five seconds.
You don't need to commit every command of the program to memory. Just like anything else in tech, knowing how to find the knowledge you need is good enough.
Can I use git like a simpleton? Absolutely. Can I gracefully recover from errors in its application? Nope, it never happens. It's a chainsaw and I ultimately have to solve the problem by using it like one.
So instead of SELECT you'd have FETCH, PULL, CHECKOUT, CLONE, READ, PEEK, and OBSERVE. And each of them could in some cases also modify or even delete the data depending on the switches.
Imagine there was no division between DML and DDL - you just have to remember which option switches change the schema in addition to doing some other things.
And then people would say "SQL is very simple, just learn relational algebra".
That's how I feel about git :)
With SQL I know for sure I can't break the database by doing a select. I know I can't change schema by doing a DML.
With git I'm pretty sure I can't break anything by doing git status, but other than that all bets are off.
There is at least one database that exists which does support a Git-like DAG for transaction-time temporality: https://terminusdb.com/
It should also be pointed out that "temporal databases" usually offer a lot more besides a linear transaction-time history. Although I've not seen anything that offers a DAG for valid-time histories yet :)
In your list of shout commands I don't see anything that could be used for merging? I guess the "language" of git could be tweaked to make it more consistent, but otherwise the problems it is trying to solve are more complex than what could be dealt with in a SQL dialect.
select ... as of timestamp;
> In your list of shout commands I don't see anything that could be used for merging?I'm not arguing for using SQL as a git interface, I'm just saying git would greatly benefit from better interface based on some consistent and clear separation of concerns.
> the problems it is trying to solve are more complex than what could be dealt with in a SQL dialect.
It's not. SQL simplified A LOT of underlying details. There are dozens of types of indexes. There's partitioning and sharding. There's online backups. There are transactions - local and distributed ones. There's savepoints and rollbacks.
If SQL databases were like GIT - selects with joins using different indexes would have different syntax because "you need to understand the underlying structure" :)
Based on how SQL and C/C++ faired in these kinds of processes we could have a standard abstraction layer in perhaps 10-15 years ...
You are setting a very low bar.
The article has a better way to assess difficulty, based on how easy it is to teach other how to use it.
However it's perhaps really that too many people are thinking they need to use git because their church says so and then have to deal with the self chosen authority.
For example, the concepts of "ours" and "theirs" when looking at changes depends on the current operation mode (rebase vs merge).
Merging is unsafe-by-default, because it auto-merges even if both branches have modifications to the same file, and there is no guarantee that the resulting file is correct.
There are numerous ways to collaborate on a git repo, with vastly different performance/usability implications, none of which is obvious when you start up (merging remote into local, rebasing local onto remote, squashing local commits; patches vs pushes).
Not to mention that, for teams that work with a centralized remote repo, the whole concept of local tracking branches adds mental overhead for nothing, and extra work every time you want to push a change to a remote branch. You have to first pull, even if your changes and the remote ones don't touch the same files. Which of course means that, if you had a dirty worktree, you actually need to run 3 commands - one to stash your changes, one to pull, the actual push, and now an unstash.
No connection to the server no committing - no confusion about local vs remote. Branching only on the server, merging totally useless - no branches, no merging, no conflicts. Want to have your local development versioned - zipfile + date time.
I would never go back to that, but from people complains some might want to.
I personally think if a..b in git log shows me a set of commits then a..b in git diff should show me the code contained within those commits, the patch files that would generate from them.
I guess this is a foolish expectation?
The "concept" of resetting? "git reset" does different things in one command: there is no one concept. It can discard your staged changes and working tree so that your workspace looks like your head. It can move your head ref while doing that. It can move your head without changing the working tree. It can interactively stage the changes to another commit (e.g. to selectively revert).
Some kind of troubleshooter GUI tool that covers 90% of all use cases would be great. I'd certainly be willing to pay for it.
If switching branches wouldn't conflict with my current change, why do I have to stash/checkout/unstash instead of just doing it?
Why can't I pull without fetching?
Why will none of the 5 or so push configurations just do "push the current branch to the branch of the same name on the remote"?
Why is there no way to stop git from setting master as the upstream every time I do git checkout -b myfeature origin/master?
Why do I have to detach from a branch before deleting it?
None of this stuff is inherent to the problem or due to being a precise model of things; quite the opposite.
What do you mean by this? It sounds like how stash already works.
> If switching branches wouldn't conflict with my current change, why do I have to stash/checkout/unstash instead of just doing it?
This is how git has worked for years: you can checkout a non-conflicting branch without stashing.
> Why can't I pull without fetching?
Have you customized Git to not support this?
> Why do I have to detach from a branch before deleting it?
When does it make sense to do this? I can understand deleting a remote branch (which doesn’t require this) but deleting the current local branch doesn’t seem to make sense in any normal workflow.
I want to switch branches when I have some added (staged) changes and some unstaged changes, and keep the same set of staged and unstaged changes afterwards.
> This is how git has worked for years: you can checkout a non-conflicting branch without stashing.
Only if none of the changes are to the same file, even if they don't conflict.
> Have you customized Git to not support this?
If I do "git pull" it does a fetch and then something else. I'd like to do just the part that's not a fetch (because I fetched the same remote recently).
> When does it make sense to do this? I can understand deleting a remote branch (which doesn’t require this) but deleting the current local branch doesn’t seem to make sense in any normal workflow.
When I've finished working on something and aren't going to work on that repo again for a bit, I'd like to delete the feature branch that I just merged remotely, but I don't want to check out anything else in particular. So I usually end up doing a git checkout --detach just so that I can delete the branch, which feels cumbersome.
Pull = fetch remote branches + merge remotes -> local tracking branches
If you want to do the second part without the first, the git merge command will do it.
From the first line in the man page for git-pull:
"Incorporates changes from a remote repository into the current branch. In its default mode, git pull is shorthand for git fetch followed by git merge FETCH_HEAD."
Git remote-tracking branches are just a cache except when they're not. A better model would be for every command that can interact with remote refs to fetch first by default (like pull does) but take an option to "work offline" and use the remote-tracking version (which would then be a proper cache). Or vice versa, for every command to not fetch unless given a parameter that tells it to. It's ridiculous to have to guess which commands will fetch or not.
2. See 1.
3. `git pull` by definition conducts a fetch because it Incorporates changes from a remote repository into the current branch.
4. Use `git config push.default current`.
5. Use `git branch --no-track new existing`.
6. I assume this is something to do with the reflog.
But git stash does keep track of what it added?
> If switching branches wouldn't conflict with my current change, why do I have to stash/checkout/unstash instead of just doing it?
If your current changes apply to files which haven't changed between said branches, you don't need to stash your changes when switching between them.
> Why can't I pull without fetching?
The command for that is `git merge`.
> Why will none of the 5 or so push configurations just do "push the current branch to the branch of the same name on the remote"?
The command for that is `git push origin HEAD`.
> Why is there no way to stop git from setting master as the upstream every time I do git checkout -b myfeature origin/master?
The option for that is `--no-track`.
> Why do I have to detach from a branch before deleting it?
Because the `git branch` command never changes the working tree, which in this case uses the branch name to identify its location. If the branch were to be deleted without first detaching (or switching to a different branch), stuff would break.
Added as in staged
> If your current changes apply to files which haven't changed between said branches, you don't need to stash your changes when switching between them.
Yeah, I know. So why do I have to stash when I've changed an unrelated part of the same file?
> The command for that is `git merge`.
But that doesn't know which branch is upstream, I have to tell it explicitly each time.
> The command for that is `git push origin HEAD`.
I want "git push" to just do that.
> The option for that is `--no-track`.
Yeah, I know, but I wish I could just turn it off for when I forget, or when I'm doing it from an IDE or similar.
* It's not actually hard.
** You don't understand it. Everyone else is fine with it. You just haven't spent the time to understand it like everyone else has.
** Ok maybe lots of people don't understand it. They just haven't spent the time to understand it like I and others have.
* It is actually hard. ** You're not intelligent enough to understand it, but everyone else is.
** Ok maybe lots of people aren't intelligent enough to understand it, but that doesn't matter because I am and so are others.
IMHO the more intelligent response is:* If people think it's hard, that's a problem, and we can use our understanding / intelligence to help make a version control system (layered on git if that works) that doesn't require the depth of understanding or intelligence to work with - for everyone.
I've worked with thousands of developers and my experience is that even the brightest still make mistakes when given sharp tools, and when you're just trying to get your job done but you've tied yourself into a knot with distributed tools that try to help you deal with merges of turing-complete text, you can have a bad afternoon.
I'm hoping darcs / pijul / something else a bit more 'friendly' becomes popular and those who want to concentrate on their code and not their tools can get some time back.
Ask your manager, which problem is the problem for him.
* It is too powerful
* It is not prescriptive
* It has horrifyingly bad UX/semantics
Git exposes all of its complexity at installation, which means that you are able to do any amount of damage from minute one. There are no cascading layers of abstraction that map onto the user's comfort level with git.
Git also doesn't prescribe workflows. Overtime, people have come up with standard workflows, but there are too many of them and they all have different mental models. The issue is that most of these workflows are only marginally better/worse than each other and don't necessarily provide additional functionality in any sense. It would be much better if there was only one way of doing things in git. It would make things marginally inconvenient for many, but the marginal loss of productivity would be more than made up by a consistent mental model and the increased reliability of the 'canon' workflow.
Last, and certainly my biggest complaint is the terrible UX and the semantics they convey. It is almost as though the creators went out of their way to have naming schemes at odds with natural language.
I hope someone builds a keras-like tool for git. Interoperable with the tensorflow (v1) that is the git underneath, but exposes a much easier and in most cases feature complete set of abstractions that work for 99% of its users.
For a good example of "user friendly git" I suggest taking a look at mercurial.
A very lovely thing is text editors without "save" button. You change the contents of your file, close the program and that's it. The boundary between "changes in memory but not yet saved" and "changes already saved to the hard disk" is an obsolescence and does not really make sense today.
Git adds not one, but three layers upon the idiotic save button. Now, after saving your changes, you still need to add them, commit them, and finally push them. What I want is less stuff, not more. All my keypresses and states of files at any moment should be automatically saved forever, without action by my part. Then, if I want, I can "tag" a state of the file tree to refer to it later. The perfect git interface should only have two commands: "git init" and "git tag". All the rest of saving and bookkeeping could take place automatically.
My hacky solution at the time was just to always do anything programming related in a folder watched by Dropbox. Then every single file modification and delta is indeed automatically stored (and away from my machine, for redundancy and safety). It's not the greatest UX when I occasionally dig through the Dropbox file modification history, but it works okay enough.
As an amateur musician, I always wondered why there wasn't any DAW that supported something like this, too. You get an endless undo button that automatically tracks all atomic actions (twist X knob to N%, change Y volume to N dB) to allow for reversions, but no system to actually view, restore, tag, or switch between anything in this edit tree beyond resorting to annoying kluges like "stashing" an older state by spam-clicking "undo", saving a copy of the project under a new file name with a short description of the state at that time, and then pressing "redo" over and over until you're back at the "present".
And when you close the program, all that undo history is gone, in which case if I feel like I did something that really messed up the whole project and which I want to revert, I have to dig through the Dropbox file edit history and download like 10 different copies of the project file around the time I think the undesirable change may have occurred, and load each project one by one to try to find the one that's immediately before that change.
Sorry for the long tangent. I just also don't see why this isn't already a thing for both source code and music project version control.
With how software devs use git, it's 100% worth it to read a good book on it.
https://learngitbranching.js.org/ (which presents a visualisation of the commit history)
https://github.com/Gazler/githug (nice for small exercises; although you kinda have to pay attention and not just 'game' your way through it).
Basically it's impossible to learn something without trying and making mistakes, and analysing what went wrong. No failing - no success. You will get it, not that hard. Good luck!
It’s way more important to understand that git has 0 consistency of what the command name is and what object it manipulates.
Git checkout can create both branches and files. Why? Wouldn’t it be easier to have two commands for checking out a file from a different branch and creating a new branch?
If you don't have time for a full book, I think Mary Cook's Git from the inside out is a wonderful start: https://codewords.recurse.com/issues/two/git-from-the-inside...
In my opinion relying too much on user understanding implementation is a mark of bad design. I don't care about more advanced functionalities of git, on daily basis I have very simple workflow that I want to "just work". Sure I can spend few days studying git internals, but it feels unnecessary. Especially given that in the past I've worked with simpler proprietary tools that "just work" (though did not have equivalent of "power" features).
On the other hand I think git is like bash - has some serious warts but it's good enough to be used widely; and unlikely to be replaced by anything else at this point.
That's just an excuse for Git being super confusing. Does Microsoft say "it's really important when using MS Word to get a good grasp of how its internals work"? Of course not.
Yes you need to get a good mental model of how Git works (basically, commits are efficient snapshots of your code), but that's not the same as knowing its internals. Do you need to know about packfiles and loose refs etc? No, obviously not.
The core idea of Git - a DAG of repo snapshots - can be explained in like 5 minutes. I could explain all of the other operations in 5 more minutes.
Maybe I should do a `Git in 10 minutes` video, but there are about a million of those already, and as I said, it wouldn't address the actual hard part of Git: the CLI.
Is (La)TeX super confusing? Sure. Is it what the pros use? Definitely. Also, read "The TeXBook", it is a masterpiece.
When I explain Git to other people I explain it as a tool for manipulating commit graphs, where every node in the graph is a (merge) commit with some unique hash, where a commit itself is just essentially a patch on the previous node(s) in the graph.
Implementation details on how this commit graph is manipulated or stored behind the scenes are not important to understand Git in my opinion.
I fully agree, that's why I built a tutorial where you learn about Git internals by implementing Git yourself in Python: https://www.leshenko.net/p/ugit/
I wonder whether we could create a much better and more consistent command line interface from scratch?
Somehow with git, lots and lots of developers (and non-developers too, but let's just consider developers) can show up and say "i've been writing code for years, i've been using git for years, I get by, but I find it pretty confusing and hard to use," and still have people saying "no, you're all wrong, it IS easy to use."
Like, how is that even logically possible? To insist that software really is easy to use even when a large number of people don't find it easy to use, is an interesting metaphysical stance.
For example on knowing branches having local and remote versions, "because why would they"..they would because if they want to use the tool effectively then they need to know how it works. This is the same reason I learned how to use git prune. Would I ever use it on production code without a backup? No.
A GUI is not the solution, because a GUI can never equal the expressiveness and capability of skill combined with a parcity of input provided by the command line. If it did then the complexity of using the GUI would be just as hard, or harder, than the command line interface. However, there are many who do not need more than basic Git. Those can be served by a simple GUI, or by pre-provisioned Git aliases with documentation of what those aliases do.
I still dislike a GUI because I have had a number of people come to me to fix things on a team that used SourceTree and accidentally did something horrible, either because their finger slipped or because they didn't realize what they were doing and the GUI made it too easy to do it.
All powerful tools should have a simple version and a complex version. Git is extremely powerful, but has no simple version for everything.
What helped training new people was telling them to think of git like a complex copy operation across computer boundaries, and explaining the commands in terms of that. Once they've gotten comfortable with the basics then you can explain how it differs from copy (and it does, greatly).
The complexity is mostly accidental and down to poor UX choices and legacy.
As an example: why is the centralized binary storage system (LFS) using http when git isn’t? The answer: because it’s not really part of git. Congratulations, you now have two sets of auth and network issues instead of one.
Git is design damage by Unix philosophy. It does one thing and lets programs interact via command line. The problem with that for a tool that humans use is people want consistent simple UX, not unchanging UX. Scripts want unchanging UX, don’t care about consistency or simplicity.
Git is simply too low level for most users. As an example, it doesn’t even know which repo is the central one! It’s so low level that repos are repos. Yet few of us would consider our local repo to be equivalent to the blessed central repository and it would certainly help with many operations.
If you're a dev/SWE you should be able to grok a semi-complex CLI API to control software... but the further the world gets into "everything as UIX" and "everything has to be 'easy'" the more we stray from incredibly powerful, immediately available CLI tooling.
I know of too many highly-paid people who literally refuse to learn the CLI `git` or `docker` and limit themselves/skillsets by doing everything through the comfort of a UI. To me, it's a mark of laziness.
Git isn't "too hard"... it solves an incredibly complex problem. It has a lot of capability and complexity under the hood to deal with all of the craziness of distributed development paradigm.
Yes.
> I think its ok to expect tooling to be easy so we can spend our times on actually writing code.
I have never seen someone use a git GUI alternative as quickly and effectively as a competent CLI user. Especially if you're dealing with anything of reasonable complexity, but still, even for simple stuff. I can hit F1 for my quake-like terminal and type out `git add . && git commit -m 'Adds [...]'`, or a `git stash`, etc. faster than someone can reach over to the mouse and even open the GUI (let alone actually committing).
That's not to say that I don't use Sublime Merge but it's only for complex visualization situations of weird branching etc. But... it's worth noting that most of the time I can get that hammered out on my GitLab instance.
So, if you're looking for efficiency and want to "spend time actually writing code" I attest your argument that a GUI would speed anything up only if you refuse to learn the CLI.
> To me it's the same thing as expecting auto completion and line by line debugging from our IDEs
I work in Sublime all day long and actually actively turn features like this off because they slow me down. Also this is not to say I don't often jump into Intellij for heavier IDE stuff (step-through debugging) but that's like 1-2 times a week max. Otherwise, get out of my way and just let me get the code onto the page, I know 100% what I'm doing/writing and my docs are immaculate and accurate.
---
Overall we probably work in very different ways, with very different development philosophies - which is 100% fine =)
Cheers!
> ...a bunch of people who are already really comfortable with their terminals, and they’re reading the email from mailing lists in their terminals already, and unpacking patches by typing out a tar command in a single go.
But even if you consider the case of "lazy" devs, I think the conclusion holds true:
> I guess this short TL;DR version would be I feel that version control systems (the next version of them) should not be something that was specifically made for the Linux Kernel community. It should be something that was specifically designed to be used by the wider community.
It has become the de facto distributed version-control system for the world, but if even people who are "highly paid" professionals struggle with the CLI, what hope for everyone else? It might only be "semi-complex" to you, but there are dozens of GUIs listed on official site[0], dozens of books teaching it and an official manual which is still a "work in progress"[1] 15 years after it was released suggesting a different view in the wider community.
Imagine if git was lost and it had to be recreated, would it make sense to rebuild it exactly as it is now? It's an amazing tool and has stretched far beyond it's original use case, but surely we can all agree that there is room for improvement in its design?
[0] https://git-scm.com/downloads/guis [1] https://git.github.io/htmldocs/user-manual.html#todo-list
I find your argument to be "if things were different, wouldn't they be different?" which I don't find to be of much substance... but let me fancy your thought experiment:
Assuming the remembrance of the features/API was not lost there would be a worldwide effort to recreate it as soon as humanly possible due to the problems it solves better than any other SCM on the market. It's critical for global software engineering productivity. I have no doubt that a similar (if not exact copy) of git would be produced in very short time.
Let's take another piece of Torvald's software and ask the same question: if Linux disappeared overnight would things be done different? Well, yes... sure. but would things also be re-created near 1:1 due to the known success of the Kernel? Also yes, and as fast as humanly possible.
I think that's a fair scenario for evaluating whether or not a tool designed for a small number of people for a specific purpose has successfully transitioned into one used by many people for many purposes.
It's awful. The porcelain is awful. Git solves problems and it has awful porcelain. Git is very useful and it has awful porcelain. Everyone would benefit from learning the basic model of git and ... it has awful porcelain.
I particularly think about this because I had some conversations with people from the open science community. It's really often where I'd like to tell them: "This problem, you really want to use something like git. Although... it's kinda hard to learn."
There's a lot of workflows outside of software development or from people who develop software, but for whom software development is not their primary thing, where a version control system would be really useful. But our current state-of-the-art version control system isn't very well suited for that, particularly not for people who have a limited capacity to learn things or might only use it every now and then.
I found working with SourceTree to be a good fit most of the time, after learning via command line for a bit. It keeps me from having to look stuff up, and is much nicer navigable than command line imho.
My problem with such answers is not that I don't want to have to memorize git commands (with all the flag and sub command variations, git config entries etc.).
My problem is that the guys from the discussions about.. ... blender, vector graphics programs, Xcode, rider, gcc, apple notarization command line tools, brew, pip install, the python3 standard library, emacs, vim, the terminal and ssh, my Synology's time machine configuration, my book keeping and tax program, Django library, the c# standard library, my insurance policies, my smartphone, smart home and my Samsung smart tv, ... ... all said that it's not so hard to memorise these few simple steps or commands, and that I should rtfm.
Not sure how useful of a retort that is to the criticism "X is too hard to use".
When I was a lad, we used to walk 10 miles every day to school in the snow - AND ENJOY IT!
etc.
Some people, however smart, try to force git to do something in particular, without asking first "How can I do x with git" (I don't think I ever had a use case where stackoverflow didn't have a solution for).
Then they end up with a borked repo, everything is confusing (because it should have almost never been in this state), angry at the tool they abused so badly.
Git is solving complex problems, and it obviously has certain idiosyncrasies. But just because you think the developers chose poorly, doesn't necessarily mean git is terrible in the first place (might also be true though, but please prove it by showing a better alternative). I heard mercurial has a lot of fans, but I had a terrible time cleaning up behind colleagues though - everything was easy for them, but they did not know what they were doing and why it was bad. The git branching-workflow helped a lot there.
Often the obvious solution of an outsider is not really a solution.
Could git have named some commands better? Yes, of course. If you don't know what git is doing internally on a checkout, it makes little sense. But this is being worked on.
I would argue that if someone comes up with his very own perfect distributed versioning system intended to be super intuitive and simple, he will in the end also build in complex constructions that make no sense to outsiders that didn't participate in thinking about the complex problem these concepts are trying to solve.
Sadly these improvements rarely make it into the public consciousness because people don't pay attention to them and instead find stale or inappropriate StackOverflow solutions.
Is has already been mentioned a couple of time in this thread, but it deserves a more prominent mention, because IMHO it's a really interesting project.
The author(s) analysed git UX shortcomings and tried to learn from them. For example, Gitless aims to align well its concepts with user's intentions. There have been written research papers (and a talk is available online) about their methodology and Gitless design:
Once you're over the hump the system is very intuitive. I liken it to awk or sed which beginners often find incomprehensible, until they understand what the tools do at which point they become simple. There's a lot of good resources out there and StackOverflow has almost every question imaginable already asked and answered.
Having said this, Git doesn't make it easy by the terminology and concepts that are used. And also the inconcise UI (you use git reset for a lot of very different actions, some harmless, some very destructive) doesn't make it easy for a newcomer. Who will often resort to just remember oneliners or look them up from a manual without knowing what they actually do.
What really helped me in understanding Git was to understand the mechanics of the database on an abstract level. Commits and how branches/tags relate to them. If you understand that commits (not branches) are the tree and the branches just post-it's you put on the commits and can rearrange as you please everything becomes much more malleable. Once you discover commits are hardly ever deleted/lost, but just the post-it's are moved (which makes the commits invisible), things become easily recoverable and fixable. Also not using code, but cats[1] also seems to greatly reduced the complexity of learning Git for me. Visual tools like Ungit[2], Tig[3], or plain Git log[4] help to see the commit tree and attached branches and gives an idea of how the data is manipulated.
There is also the Gitless[0] project which tries to redefine the UI of Git, without changing the data format itself. It offers a different look at the same repository and more clear and dedicated commands/concept to perform certain tasks. And since it just uses Git itself underneath you can seamlessly switch between it and Git without issues.
[1] https://girliemac.com/blog/2017/12/26/git-purr/
[2] https://github.com/FredrikNoren/ungit
[3] https://github.com/jonas/tig
[4] git log --oneline --decorate -50 --all --graph --remotes
Git's UI has grown organically and is still not great for common tasks like undo, however they are working on it and it is slowly improving. For example, they've just added a restore command which should make it simpler to undo changes (git restore filename):
https://git-scm.com/book/en/v2/Git-Basics-Undoing-Things
Things I'd also like to see improved:
Undoing things locally should be very simple and intuitive - perhaps restore will help.
Conflict resolution when changes happen on the same line, so that there are fewer clashes on rebase/merge.
Git log should be compact and pretty by default
Git push should push tags as well by default
Deleting tags etc on a remote has a really weird syntax - git push origin :tagname git push --delete origin tagname just feels really odd instead of using the tag command.
There should be a simple way to add all changes and commit - e.g. git add --all && git commit -m "Message" if that could be git commit "Message" that'd be great (probably not possible but at least a flag on commit would be nice). I have an alias set up for this. I like being able to add files separately to a list then commit too, but that is far rarer, most of the time I want to commit all changes.
A blessed workflow - perhaps this isn't possible but having one workflow would make it simpler to move between repos and simpler. Many projects seem to have settled on main=production with short-lived feature branches rebased off main and edit as necessary locally before sharing on main. This works well for us at my workplace.
git start - a guided tour command which steps a user through a typical workflow and shows them the commands they need (probably about 5 commands initially), and tells them the difference between local and shared commits (fine to change vs never try to change).
These are pretty minor gripes though most of which can just be fixed with some aliases for commands - I'm pretty happy with it and much prefer it to what came before.
I agree with you on all fronts, exception git add --all && git commit. I don't believe those should be joined at the hip, because staging and committing should be two distinct actions/decisions. Defaulting to including everything would lead to too many human errors and would therefore be dangerous in my opinion.
A distinct flag like git commit --all -m "foo" might be OK in my book. Possibly even adding some git config --global commit.all [default|confirm] or something.
Then again, who am I?
My preference would be a command like git save, but a flag would be fine I guess. This is a concept that most beginners don’t really want or need.
Ideally git should evolve so that beginners can learn say 5 standard commands without args, and that’s enough to get on with their work.
Working should be as simple as:
git save, git amend, git tag, git push
Make everyday use simple and easy.
It's a shame that github was created and not MercurialHub and now we are stuck with Git.
Now even Atlassian abandoned Mercurial.
The very notion of versioning terrified quite a few non-technical but otherwise very proficient office users in my experience trying to sell them the benefits of VCS. Even GitHub or Jira would be considered "for programmers".
On so many occasions I would fail to convince such users to embrace version control in their workflow, even with some Tortoise-like GUIs.
Immediacy of copying their work folder or document and appending a date or "-final" tag to the name is all their busy minds are ready to adopt. And it does make sense, no blame.
This just tells that current concept of Version Control is indeed serving the very specific needs of maintainers, not much the mundane needs of normal users. Thus the complexity of the CLI in the name of flexibility.
My expectation is that Version Control should be mostly transparent to user. It's just some internal housekeeping. On a basic level it's just a Save/Save As operation with very much versatile project-level Undo and Open. MS Office's Track Changes is a familiar workflow for many users, perhaps a similar approach could be adopted for Change Management in broader and less proprietary context.
In Git's parlance, Mr. Version Control is still a plumber that offers users some porcelane sinks, yet user's projects need to live in a whole house with already functioning works and appliances.
I want to believe that Version Control will one day become a basic amenity, not an "exotic" feature that needs constant attention.
The biggest problem I face is the conflicting information of how to do a certain thing. The other biggest problem is that my need at one moment may be similar by slightly different to a situation/question posed on StackOverflow, and so I'm left to guess if I can take the answers and work from those... or if I will end up in a worse or weird situation by following them.
It's very difficult to even discuss situations in Git, because the smallest details can be a deciding factor in choosing what next step to take. It reminds me of analog and digital electronics... sometimes you must be very precise and know exactly what you're doing, and sometimes you can just approximate. Knowing when to do one or the other takes lots of experience.
True! Too bad the author doesn't use a GUI just because they are "a Linux nerd". Magit contributed a lot to my Git understanding. And for those who don't use Emacs, I believe there are some other good GUIs out there (e.g. gitk). They allow to have a visual representation of what's going on, they show available commands, etc.
Back in the bad old days before git I was in a 20-30 person company that used Microsoft's SourceSafe. For anyone unfamiliar it had a basic library type structure where only one person could get out (lock) a file at a time.
Now the obvious downside is that when someone goes on holiday or simply forgets those locked files can become blockers. The solution to that is to have an admin unlock the files, which was pretty easy, then a merge, which is basically what happens by default with git.
The upsides of the library approach were a) that I could scan the top directory, and quickly drill down to see who was working on what. b) I feel that walking over to someone's desk and asking if they were still working on a file produced some great back and forth, that was where the magic of collaboration actually happened.
For context, we used SVN successfully for years before that without ever running into a similar situation.
Let’s also not forget that version control — and any kind of synchronization — in general is hard.
I think the git cli is a classic example of the 80:20 rule: 20% of the commands make up 80% of typical usage. While it may take a month to learn the entire git cli you can get up to speed with the basics in a few days and then dive in to the other stuff as and when you need it.
You also don't read all of the documentation of the standard library of your programming language before you start using it.
It also lands squarely in the middle of making user-friendly analogies and allowing you to go "directly to the metal". The commands are a super leaky abstraction and often you need to simply memorize what they really do, no real deduction possible.
That being said, I think Git's command-line is becoming simpler -- I don't use GUIs since SourceTree failed to make me notice I was in the middle of a merge.
That is, version control is difficult and git is a powerful tool that exposes that difficulty and the many (complex) ways to approach version control.
Google's perforce with mercurial client has been the best VCS I've ever used and I now have a deep hatred of everything that isn't that system, especially git.
The author of Darcs, David Roundy realized that Git was going to dominate so started a "best of both worlds" project that used the storage format of Git but the UX of darcs. That was called `iolaus` and never really launched as a usable project before was abandoned:
https://github.com/droundy/iolaus
That's still my preference for what a rethink of the Git UX should be.
By this point I've learned many of the pain points of Git. By having experienced Darcs, it's frustrating to teach Git to newcomers knowing the experience and ease of use could be so much better.
More context:
* https://mark.stosberg.com/blog/2008/11/darcs_vs_git_annoyances_push_-dry-run.html
* https://mark.stosberg.com/blog/2008/11/darcs_vs_git_annoyances_pushing_specific_patches.htmlNow, I have strong disagreements with GitHub's semantics. I want code reviews to be per commit, not per branch, and I want an easy way to stack up a bunch of commits, make changes each of them as I get review feedback, and then merge a whole range at the bottom of the stack as I they are accepted.
Right now I do this by living in git rebase -i, putting a little tag in each commit message to name what remote branch it should be pushed to, adding an exec command in my rebase -i that extracts that branch and does the push, and then working with wiring together all these remote PRs on all these remote branches.
Happy to show you how to use it - just book some time here: https://calendly.com/ericyu3/15min
Please read through the first few chapters of the official git tutorial[1]. Once you get the mental model right, git is immensely simple to use.
I highly recommend sticking with the command line.
Github on the other hand, was designed to solve a whole different problem.
FWIW if you're on Linux (unsure about Windows and Mac), I happen to have zsh and oh-my-zsh[2] installed. They add a ton of incredibly useful git aliases. So for example, seeing a tree view of your project is a simple `gloga` command. Helps by not having to remember the equivalent full command that gives you the same result.
We use a very basic GitHub PR squash+merge process. One other person must review all code and it must pass checkbuild. Simple enough. To avoid horrible conflicts we have daily standups where we make our work areas known so these concerns, dependencies and blockers can be handled asap.
For us, a PR/branch that lives longer than 48 hours is rare, so things don't have a whole lot of time to get fucked up. If we know we are going to be working on something longer term, rebasing after every merge to master is strongly encouraged.
I use cli for pretty much everything else. I don't get the fetishization of the cli, it's just another interface. For source control operations are much easier to grok as visual operations and I advise all new developers to start with a client like gitkraken and delve into the cli if they really need it (in most cases they don't).
We could probably make a new and better command line interface that brings out the underlying simplicity more.
Git's UX, like a famous programming language, was never designed in a strict sense. It's clearly been written to solve immediate requirement, one by one, without a vision (again, from a UX perspective).
Result: the horrible checkout command, which does a zillion different things, and I bet only few users know all of them. Same goes for reset.
I don't remember all the checkout forms, and I couldn't use git without aliases.
The porcelain interface is another one. Excerpt:
This is my fault, to some degree.
The "short-status" form is meant for human eyeballs, and was designed by Junio.
Some people wanted a scriptable status output, too, so I slapped a "--porcelain"
on the same format that turns off configurable features like relative pathnames
and colorizing, and makes an implicit promise that we won't make further changes
to the format.
The idea was to prevent people from scripting around --short, because it was never
intended to be stable.
So yeah, while --porcelain by itself is stable and scriptable, it is perhaps not
the most friendly to parsers. The "-z --porcelain" format is much more so, and I
would recommend it to anyone scripting around "git status"
Note the "slap" here; it's not random.Commandline is not easy, it is powerful: that's why we use it, that's why we love it.
We don't have to know exactly all the command parameters except one or two: if need more, make a script/an alias or use --help or man; there are many ways.
As long as we keep it powerful and can script it, it is good for me. Actually, most of the time I use a GUI for git, because that's what the tool allows and as a human I feel it more practical. But sometimes I go beyond the GUI and use some very specific commande to get back the raw power of it.
GitHub drooling now that their extinguish end-game will actively be welcomed by the community.
I'm not a git expert. Just a developer who likes to get things done with the least amount of effort. I use a combination of git cli, vscode git extension and SourceTree to do everything I need to do. I hate that I have to use SourceTree given its many flaws. Yet, the way that it lets me visualize branches-merges history and do interactive rebase is just unmatchable.
Also, never understood why Github Desktop exists or what people use it for.
There's a good reason for this! Git is really worried about automatically doing something you don't want and losing data or mangling code. One way to deal with that is to teach users how many decisions git is making, and then if there's any doubt git will refuse to make a choice and tell the user to sort it out.
The approach is both sensible and demands a great deal from individual users. Especially users who are newer to the system and, in their inexperience, more likely to get into bad states and be uncertain about how to get out. I suspect that, on a practical level, more changes are lost by users needing to reset --hard because they don't know what else to do than git would use by making a few more choices. But there is value in the idea that when that data is lost its the user who chooses to lose it! I don't want to lose that.
I think there's a huge hunger for a more automatic DVCS, one that offers fewer options and makes more choices for you. There are obviously a lot of other options out there at various stages of development and I have no idea what they are like because, like many experienced programmers, I'm quite comfortable with git!
I hate git with a passion and am very happy with svn. Even my business users can learn and use TortoiseSVN in one session.
Once you separate the two skills you get 4 classes of people (with gradations):
1. don't understand it, cannot explain it. 2. do understand it, cannot explain it well. 3. don't understand it well, can explain it well. 4. understand it well, explain it well.
Number 2 are good practitioners and not as good teachers. Number 3 are good teachers but not as good practitioners. Number 4 are good teachers and good practitioners.
Everyone wants to learn from a number 4, but they are more rare then the 3s and 2s. Between a 2 and a 3, you'd rather learn from a 3. If you don't need to learn, you'd probably rather work with a 2 than a 3. Basically, even if their mental model isn't perfect, they deliver explanations that can quickly lead others to at least be as good as them and possibly better quickly if you can see the mistakes in their mental models (their descriptions could potentially be 100% accurate without it reflecting their poor mental model).
Anyways, this observation leads to the standard cliche, "Those that can, do; those that cannot, teach."
I too have had to clean up git mistakes of collaborators for years, almost all of them rooted in a misunderstanding of what git does, or carelessness (amplified by git's arguably less-than-stellar naming conventions). But is there really any chance that any DVCS will be "easy" (or "not too hard") for someone who hasn't thought about and internalized what the goal of a DVCS is? It seems a bit like a person who only ever spreads butter complaining that knives are needlessly sharp.
PS: My greatest success rate at converting people from "just hammer git commands until my code is on GitHub" to actually understanding what problem git tries to solve, and how to interact with it, has been from Mary Cook's wonderful Git from the inside out (https://codewords.recurse.com/issues/two/git-from-the-inside...)
> I have some changes. I wanna share it with Jon and Johnny so they can tell me what they think. And then maybe they can add their ideas. And then we can have a merging of our ideas, and eventually test out if it works, and have it out there and ship it.
Fundamentally this is the problem. If this is your use case, then git is not for you. But this is not really a use case because people have not thought through the complexity of what a "merging of ideas" means.
If you want the simplest version of this, just use a google doc -- you get history, collaboration, all of that. It's a fine tool for what it does. You don't have to worry about backing up checkpoints or anything, or sending around multiple drafts for revision and comment -- all of that is directly included.
For people who need to manage versions, in order to use git you have to acknowledge that you can no longer treat your version control as an annoying little checkpointing thing that magically shares stuff, because that model ALWAYS breaks in reality; anyone who has used CVS knows this. Anyone who has had to do branching in Perforce or SVN knows this. You have to understand how it is implemented under the covers.
Fortunately, git is really really simple under the covers -- there's no deltas or change records, just an efficiently stored snapshot of the entire tree, and when you commit a change, it stores an efficient snapshot of the entire tree. The previous snapshot is still there, as are all previous snapshots.
Then it's just a matter of learning how each of git's commands map to changes to the underlying data model.
That's exactly the point the author was trying to make. Make Git so abstracted from the underlying tech it comparable to a simple task as editing a Google doc.
> If this is your use case, then git is not for you. Well google docs can't have testing, it can't have merging as it is inherently "merged" already, etc. so totally not the use case the author was referring to.
Most experienced developers are used to this. Most other version control systems have similar issues. I started using Git 15 years ago by means of running it against subversion via the git subversion plugin. That forced me to learn a few things in a hurry and made me realize just how limited subversion is. I got into that another five years earlier by migrating a code-base from cvs to subversion. 20 years ago, using cvs was considered acceptable as a version control system. Neither of those were particularly user friendly but they were a lot simpler to use because there was only so much you could do and even less that worked well enough that you should do it (like branching and merging).
Git UIs as attempts to make git user friendly seem to be mostly not very successful. I always struggle how to do even basic things with git in IDEs like Intellij or VS Code because they seem to insist on coming up with their own terminology. I mostly ignore that stuff and do it on the command line. I use a simple mac tool called gitx as a ui for viewing diffs and writing commits. But I push, rebase, merge, etc. from the command line.
Github is the exception. It's awesome as a web based UI. And it's the reason that git became the dominant remaining version control system against a long tail of things like darcs, mercurial, and other decentralized version control systems and an even longer one of legacy/obsolete ones like subversion, cvs, etc.
None of those are any better in terms of UI and at this point basically all of them are magnitudes worse when it comes to being properly integrated into other tools. So, that kind of is why Git 'won' and why the barrier to entry for new tools is very high.
But git could definitely do with a rethink of the porcelain at some point. I think the issue is most of the interesting problems are on the plumbing side and hence most people get stuck in protracted wanking around diffing algorithms rather than actually fixing the UX issues. Techies are just not good at UX. By the time you 'get it' well enough to fix it, it's no longer a problem for you.
I run UNIXen as my desktops (Linux, Solaris, BSDs) even if it takes more understanding and tinkering than OS X, because in the end it's more powerful. I run my own email infrastructure instead of giving it up to gmail, because it's more flexible and powerful and I'm in control. And so on.
But git? What a curse it is. I identify with the comments that liken it to hazing. A lot of pain to be inducted into the club, just for the sake of pain. No gain.
I've been using source control systems for many decades and all of them have been tools that provide their value without being intrusive. Never have I had to fight a source control tool or take backups before every operation like with git.
So that explains the hate, from my perspective. git came along and polluted a perfectly good tool space with something extremely user-hostile and didn't add any extra value (no, git did not invent distributed source control so that's not the explanation; I've been using distributed source control since the mid 90s and today I use mercurial wherever I get a choice).
At the same time, many tools could actually be a lot better and if we all magically traveled 50 years into the future we would find all these better tools and see that it wasn't only the dumb/lazy people who used them - it would be everyone. For example, how many people write applications in low-level languages like assembler today? Not many - but at one point that was the only option and anyone who complained about it would be labelled as a lazy worker.
The signalling aspect of this certainly distorts the discussion, but bear this in mind:
It is simultaneously true that git is a tool with a poor interface and a bunch of warts AND every aspiring developer should do the work and learn it in detail so they can use that knowledge to signal to people that they're not lazy and/or dumb (and the lazy/dumb people - even knowing this - will not do it, so the signal works).
Also—I'm a language guy. Picking up languages, reading in other languages, just "clicks" for me. But math? Pffft. Forget it. I barely scraped myself out of college with my CS degree intact.
I learned Russian and Spanish just for fun!
My theory is that git is learned like a language and retained like a language. Tools like "GitKraken" are just "Duolingo" for your brain. They don't replace immersion learning when the stakes are high. (Not claiming this is the "best" way to learn, but boy is it effective)
Anyway.. I've never really struggled with git, nor with it's advanced notations. But algorithms? Hard, math-related thinking? That's an every day struggle. Perhaps the author's opinion is geared from the perspective of more functionally-paradigmed thinking?
It's a bit like raising kids. You don't bash them with the intricate model of the world that you have developed at an age when they are not ready for it. The police are the good guys, the criminals are the bad guys. Sure, there are places where it's the other way around, but you don't really go about telling them about corrupt police departments or authoritarian governments when they are three years old. The goal is to build a mental model that is a good and usable first approximation of the world that they live in. There will be plenty of time to get into the details and edge cases later on.
Similarly with git, you can very much give someone a good and usable first approximation that lets them be productive with it quickly, and then go deeper as needed.
If, however, your normal git workflow involves using a lot of git features that were originally implemented to solve certain edge case situations, then this is not really git being complicated. It's people making it complicated for various good and not so good reasons.
And it's not just software engineers who tend to be 'know-it-alls'. Just spend some time on Quora.
The part about kids is a bit uncalled for though. Anyone raising kids should strive to be a specialist at raising kids, don't you think?
Also, modeling your tools around "how people think" is the wrong approach. Tools should be modeled around the process flow, and people should be taught to think in terms of that same process. "How people think" should not be leading, the process requirements should be leading.
> I have some changes. I wanna share it with Jon and Johnny so they can tell me what they think. And then maybe they can add their ideas. And then we can have a merging of our ideas, and eventually test out if it works, and have it out there and ship it.
So, no. You don't "have some changes". You have a piece of software source code. That source code is worthless without running it (or shipping it). And once you start running it, people (including yourself) will start to rely on how it works right now. If you change how it works, you need to
a) be able to explain what changed from one version to the next
b) be able to revert to the previous version if the new one is problematic
The first rule of source control is that it's not about sharing: it's about auditing your changes. From there you can start to work out the details, about sharing the source code with others, about developing multiple features in parallel, about maintaining multiple versions off the same codebase, etc.
But in the basis, git (or any vcs) is not a sharing tool, it's an auditing tool. Sharing is secondary.
> and then I have to ask them:
> > Well, what do you want to do? Do you wanna delete a local branch, and then just get it recreated when you pull again from the same remote? Or delete the remote tracking branch? Or delete the remote branch?
I struggle to think of a reason why you would want to delete a remote tracking branch only. Maybe as part of a bulk cleanup if your tab complete list gets too cluttered and you want to remove ones that don't exist on the server, but that's an advanced topic.
So for most users, it's "Do you want to delete your copy or the server's copy"? This is just the kind of user focused language that the author highlights as simple and complains git makes it hard to think about.
The git UI sucks. I'd rather we were in a world where mercurial won for that reason alone. But it didn't, and I gave up that argument years ago. But the example given feels more about DVCS in general, which removing the distributed part feels like throwing out the baby with the bathwater.
Except this one:
>> I will get you to think about a directed graph or as operations on a directed graph
> No human thinks about that!
Well, that's not wrong, people don't usually think like that, but people also don't usually think about possible specimens living in some forest during a hike, or the odds and the reasons why a given storm could become a hurricane when they read about it in the news, or all the most likely reasons why a given body part might be hurting. No, those are thought by zoologists, meteorologists and physicians, respectively.
With that in mind, I see thinking about graphs and other areas more complex of version control as being, similarly, part of the job and the cognitive load of software engineers.
In short: People don't usually think like that, but, in my opinion, thinking like that is part of a software engineer's job, so I don't see an inherent problem with that.
Getting dirty with git when you really wanted to build the product sounds a lot more like the zoologist binding and gluing together his notebook in the middle of the forest.
For instance, an analogy with zoologists I would make is knowing how to set up their observation equipment in whatever remote area they're doing their research. They have to do it and they have to know how to do it, and maybe they even have to do troubleshooting in case something is not working quite like it should. None of that has to do with zoology per se, but it is part of a zoologist's job.
They can get better and/or more reliable tools over time? Absolutely, which is what I think most of TFA is understandable. I happen to think that git is already a pretty good tool, but I absolutely do see why many people disagree.
I really wanted to like Mercurial. UI seems much nicer. But there's no support from major tools. Cmdline tools are slow on startup - not Mercurial's fault as such, but affects me as the user - in particular waiting for the cmdline prompt showing Mercurial branch etc. Learning materials are a bit confused - so many different types of branches, a lot of popular materials seem out-dated, etc. Everyone in the whole world knows survival Git, very few know anything else.
Long story short, if I were setting up a collaborative software project (be it commercial or FOSS), I would reluctantly but unwaveringly choose Git. Truth is, 95% of the time it doesn't get in the way of getting work done, and the remaining 5% is not worth going against the grain on all the above points.
Git is still too hard to pretty much every non-developer workflow, and wouldn't omnipresent versioning (but not at the full filesystem level; with branches and explicit merges) change the world for the better.
One thing I would give up easily is decentralisation - a centralised model is more straightforward, and, for better or for worse, most people use Git in a centralised fashion.
Conflict resolution is one of the hardest version control tasks for beginners. Maybe it could be made easier by making the VCS AST-aware for more legible diffs, or by automating conflict resolution altogether with CRDTs or OT.
There were some interesting, very different takes on version control envisioned for darklang:
I think of git as a filtering function. It’s hard but changing stuff is dangerous. So I figure making people spend a few minutes googling to be able to do something isn’t so bad.
That being said, it’s used by more non programmers than any other tool.
I always hear problems that someone couldn't clone a repo as the repo got big and it's only 2GB in size and random blogs tell you to run git config command to fix which isn't even available on Windows if the user is only using a GUI tool and the other solution is to edit a .gitconfig file which Windows have problem handing files with dot at the beginning, commits creates a conflicting branch because I pushed before I pulled files I didn't even touch, and push randomly fails on people but it works on a retry etc etc.
People just figured Linus' work is a magic bullet to everyone's problem but I guess people jumped on it with no evaluation and we're all bleeding from this.
We need a better tool than git.
I miss tools like bazaar when they mention their goal was being user friendly which is important.
Starting from scratch and building a dumbed-down version control system for simple users vs. kernel developers is not the right approach, IMHO. As they say: "build a system any idiot can use, and only idiots will use it." Or you will end up incrementally adding more and more advanced features to it.
The machine world is the machine world, and the human world is the human world. Git was built to match the problem space and not human intuition. This is why we still use it while no one who doesn’t have to uses cvs or svn anymore.
Of course it’s not easy for the beginning to intermediate coder to understand. It wasn’t written to solve that problem, it was written to support Linux kernel development.
What’s nice about git is that the interface stabilized years ago. It’s not going anywhere. Alternative git interfaces are everywhere, but only one is really any good, Emacs’s magit. There’s nothing stopping you from writing another one.
Or just do what the rest of us do when we encounter historically-entrenched ugliness. Learn its eccentricities and move on.
But point well taken, we want an easier and more usable tool. I definitely think the learning curve for beginners needs to be shaved off somehow.
In general as long as you have a clean remote you can fuck around without worry because you can just throw everything away and start over.
In fact, on my teams, I make sure people use the CLI and not use a frontend wrapper so they grab the concepts before they go "willy nilly" into the comfort of GitLens or another UI that masks their understanding of what they are actually doing.
You should always understand the underlying commands you're executing. Rebase, merge, branch, etc. aren't easy concepts to understand and they aren't easily conveyed for beginners in a graphical tool.
Honestly, I would really love to know, because I have to teach git fundamentals in a couple of months at work.
The "client" is your knowledge of its data model, mental mapping of obtusely named commands and flags to things you want to do, and ability to visualize/predict the outcome.
This isn't clear to learners because git manipulates a flowchart with a CLI—a graphical activity misrepresented and disserved by its nongraphical interface. It isn't obvious they need to do the work themselves the software could be doing for them, or that they're working at a different level of abstraction than they think.
Teaching the model first, before the commands or anything else, can prevent a lot of confusion.
Understanding the origins of git and how it compares to the modern Github-is-git workflow really propelled my understanding of the tool and why some of the things that seemed weird to me actually make a lot of sense with that context.
Read the various stores of git blunders in this thread with the idea in our head about how it would be different with this change.
There's a learning curve in understanding version control, not just git. The git manual/handbook covers all of this, including reasoning, but the way that the industry carries on is as if git is a side dish that accompanies the main meal. Git is not like that, it's been here 15 years and deserves investment like a programming language, or a text editor (see Vim/Emacs).
I disagree that you need to understand the internals, but it can prove useful.
And I would argue it's the other way around. I haven't seen a Git believer who would give up his blind belief in Git even if there are way better alternatives. So it's the opposite camp which got stuck in their mindset I would say.
For example, I had a git repo on a web host and wanted it moved to another host (they cloned it easily enough), but then I wanted to make the cloned repository "authoritative", but I after several hours of looking for an answer I finally gave up. I was able to clone the new repo to my local machine, but I couldn't push changes to the new repo, and had to log into the new host using the console and commit changes there, which was still looking at the original repository.
But there is a simpler (although less efficient) method. Just simply git clone the new repository onto any machine you want. The clones will naturally be configured to point to that new repository as their upstream.
`git remote rm origin`
`git remote add origin new-url`
- add a new remote
- push your tree to this new remote
- remove the old remote (optional)
And that's it.
You're further not supposed to make commits on a remote directly. Usually this fails hard, for a reason.
I think the real solution is branch protection, however.
I think the hard part is explaining the distributed nature of the tool, where your branches are completely separate from the branches on the server. When I'm explaining it, I usually talk about branches as work streams, and merging branches means merging work together.
What kind of things tend to trip people up when explaining Git? Maybe I should write a blog post or something...
It was much simpler to use than git, but still gave you the important functionality. It had a clean Python implementation. (Actually it was the first open-source project I contributed a patch to.)
Alas, like many Canonical products, it was a good idea that failed to take hold. While git is technologically superior (more features, better performance), I like to think there should have been space in the world for a more user-friendly VCS to co-exist.
Your workflow should be pretty simple.
Go to a feature branch, make changes, add/commit changes, push up the branch, ask for a review, merge the request. This workflow is independent of the technology and can be implemented by git or anything else. There's a handful of commands involved.
When you're newer and make more mistakes, or if have more advanced needs, you can use other commands like rebase, reset, cherry-pick, bisect, etc.
Git is far simpler than the algorithmic crap we get whiteboarded on, or maintaining a complex web app.
But the github cli tool being pushed on github as the defacto user interface feels like internet explorer all over again.
And this media flurry at the same time as the switch on github away from ssl links is disheartening, frightening, and just another example of Microsoft's fingerprints on this product and our ecosystem.
Combined with the recent DMCA takedown fiasco... I cannot wait until if or when web 3.0 decentralization makes these problems non issues.
Centralisation is easier, but generally the wrong solution. Git is distributed by design, and most of the difficulties come from that. Github makes git easier by making it centralised, and that makes it easier to use, but actually make it bad in some other ways : the the recent youtube-dl debacle.
I wrote about some of the things that had to click for me here: https://henrikwarne.com/2018/06/25/6-git-aha-moments/
Particularly on teams that like to keep main clean and avoid reverts and merge commits in favor of rebasing. Thankfully my current team likes to keep their PRs clean and main is whatever works.
That and merge conflicts, especially on a stale branch. I use cli for most things and Intellij's merge tool for merge conflicts because I can get a clear view of what's what.
And it seems that all the posts on the changelog.com platform use highlights. I wish more people and articles did this. I actually built Kontxt (https://kontxt.io) so everyone can add highlights to websites they visit or own, but it has more interactivity with inline comments, polls, mentions, tags, and smart navigation.
Please everyone, highlight everything! It's so useful!
What a ludicrous article. We're dumbing ourselves down to pander to the most common denominator.
Keep in mind, the author of this article is affiliated with Github. This doesn't bode well for Github at all.
Maybe they should try? Just because I can describe with words what I want to accomplish doesn't mean the implementation will be simple. I'm all for making abstractions over git but the underlying model is extremely robust.
I think the UI layout could use some adjustment though to be fair. Reset is one of the worst offenders in my opinion.
Github has done a lot to make it better, but even github is confusing for non-technical people.
We need some merger of tools like github with everyday applications. In the same way OS's provide a file picker, github should make a "branch/file picker and committer" so that regular people can contribute to things stored in git.
Subversion integrates beautifully with third-party apps: Windows File Explorer (Tortoise), Qt Creator, Visual Studio, macOS (Cornerstone), Help & Manual, etc.
A GUI interface makes one more productive. I can right-click on a file or directory in Windows, and display all the change history at a glance.
I think Atlassian could come up with something suitable.
I studied theoretical physics and learnt SQL for a job (as I'm sure most do) but have no issue with git. In any case, you have to learn how git works to use it effectively. That doesn't come by magic when doing comp sci, as far as I know.
>git reset --soft HEAD^
That preserves your work, but it uncommits it. You can now make changes, re-add files, and recommit. If you want to destroy the last commit instead, replace --soft with --hard.
>git push origin +mybranch
The plus sign forces an overwrite of the remote branch.
I've used this technique countless times, for years. It works fine.
Merge conflicts are easy to solve now and I never get lost in the complexity.
I use cli tools for almost everything, but Git Graph and vscode solves git for me. The only command I run in git cli is git clone or git unit.
There's no way kernel devs would want to change the course of git to target different audiences. It was meant to be as their tool which is a niche and we should've known better.
Since I read the git book, I never once had to rm -rf + git clone, and I've never been stuck in any situation.
It's the same thing as people blaming regexes or CSS for being hard without reading full courses.
Initially I had thought one page would be enough. But as I started, it went on and on. Still there is much more. At a point I had to stop.
Git supports many different development workflows and it isn't reasonable to optimize a GUI for all of them. As a result, GUIs for git always feel cluttered and overwhelming or under-featured to me. I'd much rather them focus on making the CLI more intuitive than spend time on yet another git GUI.
It is ok when you create a branch from develop, code your feature and merge back to develop.
But then things get messy: you need to backport that feature to some release branches.
And all that is asynchronous (backport feature « n+1 » but not feature « n » nor « n-1 » from develop onto branch 1.0 LTS and branch 2.0-SNAPSHOP. ok done? Perfect, let’s ship that. Good feedback from users? Ok cool. Now do the same with « n-1 »)
you want to keep track of code movements between branches, so you use merge (not rebase or cherry-pick).
Pffffiou I honestly do not know how to handle that at scale with Git.
[1]: https://www.reddit.com/r/git/comments/9b80ks/how_to_restore_...
And honestly, once you understand the concepts of git, you don't need to remember the commands, you need to search for it. Just like you search for all sorts of problems in whatever language you're writing in.
I never used the GUI. It seems really complex for what we decided to be our workflow. Git is a complex software that can solve complex contexts, but you can limit your daily workflow to a few commands.
And I'd agree.
A graphical client like Sublime Merge makes it easier, but not easy.
This would also keep history of branch changes on the server side, making force pushes trivially revertable.
Learn the core commands, keep yourself disciplined, stick to a workflow, and git is fine.
This is a highly technical tool not for the average person, but it is neither designed for nor used by the average person.
Also, people must cope with the fact that "undoing" something that has already been pushed isn't just like typing Ctrl-Z in a text editor. If you're the only developer of the repo then no problem - rebase like there's no tomorrow and nobody will complain. If you work on the same project with other people, then you must take into account that someone may have already pulled your commit and added something on top of it, and you can't simply "undo it" without breaking his/her git tree unless you rebase. It's not a limitation of the tool, it's a common solution to a common problem in versioning systems.
And the confusion about local and remote branch just vanishes once one figures out that there's a local copy and a remote copy of the repo, and those may not necessarily be in sync - of course, it adds a layer of complexity, but it solves a lot of other problems when collaborating with multiple people on the same code base.
I believe that git is really the best version in system around. The way it works may have a bit of a steep learning curve, but once you master it you realize that its entities and functions (commits, branches, tags, reverts, rebases, submodules etc.) are really the best way to solve the problem of distributed software development without adding any more complexity.
The only argument one could make against git is that its cli is sometimes confusing and inconsistent - checkout can do tons of things, from resetting a file to the original version to create a new branch; some branch actions can be done through git branch, some through git checkout, some through both; you can pull --rebase, or you can run either pull or rebase alone as commands, but one pulls things from the server, the other is used to manipulate commits on the local copy - unless you want to change the commit message, and in that case you use git commit --amend.
I agree that the cli nomenclature is sometimes very puzzling. But let's really try and separate the discussion around the technology and its implementation (which is, IMHO, absolutely brilliant) from that around the user interface (which is sometimes inconsistent, but it's also the result of adding more and more functionalities on top of relatively few existing commands).
I mean, git is hard, but it's a big improvement over what we had before. And so will whatever replaces git be, whenever it shows up.
It’s a sad state of a world we live in. :)
As a checkmark on a resume, knowing git doesn't mean much. Most developers know how to branch, commit, push and pull. Maybe they know a little bit of reset to get themselves out of bad situations.
We had one highly-skilled developer with a background in contributing to very unrelated FOSS join a frontend team once, adding a rule about avoiding merge commits in PRs. Within a month or so they all learned how to rebase and cherry-pick.
Git as a skill needs to be taken more seriously, not something you learn on the way to doing actual work.
Well, my pet peeve has always been git-tag. When I discuss about technical documentation, I actually use man git-tag as a reference of what NOT to do.
The summary (called NAME in manpages):
git-tag - Create, list, delete or verify a tag object signed with GPG
... which might make sense but is already confusing to a beginner because of its reference to GPG (are all tags signed with GPG?).But DESCRIPTION is actually the best:
Add a tag reference in refs/tags/, unless -d/-l/-v is given to delete, list or verify tags.
Unless -f is given, the named tag must not yet exist.
If one of -a, -s, or -u <keyid> is passed, the command creates a tag object, and requires a tag message.
Unless -m <msg> or -F <file> is given, an editor is started for the user to type in the tag message.
If -m <msg> or -F <file> is given and -a, -s, and -u <keyid> are absent, -a is implied.
Otherwise, a tag reference that points directly at the given object (i.e., a lightweight tag) is created.
A GnuPG signed tag object will be created when -s or -u <keyid> is used. When -u <keyid> is not used, the
committer identity for the current user is used to find the GnuPG key for signing. The configuration
variable gpg.program is used to specify custom GnuPG binary.
[... spoiler: it doesn't get any better]
So this should be a description that makes beginners understand git-tag.Instead, it is a sequence of unrelated sentences that merely describes functionalities in response to command line arguments, in a very convoluted way (I think "If -m <msg> or -F <file> is given and -a, -s, and -u <keyid> are absent, -a is implied" is a little gem).
This is how I would write it:
Create, view, and delete tags.
By default, it creates a new “lightweight” tag, which is simple a reference to the current commit (eg: “git tag v1.2”). If you specify “-a”, a “annotated” tag is created instead; an annotated tag is still a reference to the current commit, but also remembers the date in which it was created, who created it, and optionally saves a message associated to the tag (like a “commit” message for the tag).
Annotated tags can also be cryptographically signed with GnuPG, using “-s” instead of “-a”.
You can also tag a commit which is not the current head by simply specifying it on the command line (eg: “git tag v1.2 abcde1234”).
Use “git tag -l” to view the list of all tags.
Use “git tag -d” to delete a tag.
So I think git still has a long way to go with documentation. git clone [repo] (download existing project)
git init (start a new project)
git checkout -b [branchname] (create a new branch)
git checkout [branchname] (jump between branches)
git checkout -- [filename] (reset changes in given file)
git reset --hard (reset evertyhing)
git clean -f -d (remove leftovers after reset --hard)
git status (see changed files)
git diff (see changed lines)
git add ./[filename] (prepare file(s) for saving)
git commit -m [commitname] (save changes)
git push origin [branchname] (push changes to remote server)
git merge [branch] (merge two branches)
I've been using these commands exclusively for the last 12 years or so. These are the ones I know by heart. If I was able to get by only using these than it's likely you could also survive knowing nothing more.Rebase is still confusing at times. I did cherrypicking multiple times, but usually Google that just to be sure.
Squashed a few times, but this I also Google.
Reverted a commit a few times too, Googled.
Changing commit message and unstaging is more common, but still do it so rarely I have to Google it as there's no point in memorising (one day might finally remember them, right now I know it's reset soft and amend, not sure about syntax).
I do not use git pop and git stash because microcommiting is better and less confusing and leaves no trash behind (just my opinion, might be wrong).
Maybe I've missed something but if you're taking it slow and do not make any serious fuckups with git it's all about add/commit/push, 99% of the time. I know I might seem lame to most of you as there are more git ninjas on HN than anywhere else, but I honestly just did not need any other commands and I've been working for companies as big as 500 devs.
It's a whole different story once you do something wrong, my strategy is to think 10x about everything I type after 'git' and never had any issues, but when they happen - I just Google again. Worked every time, so far. I feel although I know shit about git I'm pretty confident using it, I've seen many mid devs who still have trouble with mental models of merging stuff, people merging "dev" branch to feature branches etc. is something that happens to other folks quite often.
To sum things up - I think git is extremely hard if you want to use it from top of your head to fix complicated and not that common issues. If you just want to use it, survive and not necessarily understand all the mechanics behind it - it's as easy as HTML.
I sympathise with the article, though I'm not sure git is to blame here - if you have to revert a branch from remote once in 2 years there's no way you're going to remember how to do that. Without UI you will need to search for the solution every time, and it does not matter what command line tool or version-control system you use.
Why is "name only" split but "oneline" is not?
Otherwise I agree with you; with my team I documented the standard feature/bugfix development process including the git steps, last of which is the lead engineer merging the branch and deleting it on the remote.
What make it less hard is something like vscode, just click the file you want to register the change that you made for, make a nice description, sign and date (commit).
I also went through the xkcd 1597 phase, we all do, but over time you start to appreciate the beauty. Like all hard things, take it easy and allow yourself to learn.
Maybe something easier will come along in the future, but also making it better will probably very difficult. It is more likely that more convenient layers are build on top of Git, imho.
No. It really isn't.
> Oh, I just pushed a change. I really didn’t wanna push that, so how do I undo it?
It's always possible to reset the head back one. You "really shouldn't" because this will cause issues for anyone else downstream if they had already pulled, but this is an issue common to CVS, SVN and probably most other VCS. Arguably the Git approach is best because it actually provides a structured way to do it, and offers your downstreamers an escape hatch should they decide they don't like what you've done. As somebody else pointed out, it's like trying to unsend an email. I think you've more wiggle-room than with email though since there is a possibility to correct the record, somehow.
I'm not sure how you would do this better, a system of notifications perhaps but arguably this is something for the tools sitting atop git, and is actually "made possible" by git vs other VCS.
> How do I delete a branch? / Do you wanna delete a local branch / delete the remote tracking branch / Or delete the remote branch?
If they're coming to you it's almost certainly the remote branch, although the alternatives are so trivial they're barely worth mentioning. Most people will approach learning something new in terms of what they already know, and if they've ever used version control software before they're almost certainly thinking in terms of the old, centralised model.
> A branch is just a single concept in our head that is made complicated
I would say it is "clarified" - just like we never needed to worry about quantum effects and the classical model of physics was fine, it does one no harm to update your mental model to accomodate these things when they come to light. In a distributed setting it absolutely makes sense to be more cognisant of the split realities of two nodes in a distributed system. [0]
[0] https://en.wikipedia.org/wiki/Fallacies_of_distributed_compu...
> I have some changes. I wanna share it with Jon and Johnny so they can tell me what they think. And then maybe they can add their ideas. And then we can have a merging of our ideas, and eventually test out if it works, and have it out there and ship it.
There's a couple of things wrong with this, but the most glaring is that there are many many ways to do this first of all, but secondly it's not what git is for. It's for version control. To the extent that it supports collaboration it's still a version control tool. You can absolutely email your diffs, or put your code on a share, or do demos or exchange design documents but to me at least Git is an improvement on all of these.
> But then when we come to physically typing out all those commands… suddenly we need months or sometimes even years of learning this set of tools to become proficient enough with them.
Nobody complains about the C compiler command line? You figure out what you want, and you embed it in a Makefile or something, or you learn the commands that you need to know to do 90% of your stuff.
> I have really initially resisted the idea of graphical tools for Git, because I was this heavy terminal nerd; I was very much in my terminal bubble of being really proficient with a lot of these things,
Ah, here. Let's be clear, while I think it's important to maintain contact with the command line in these matters, you really, really need to have some good tools or you really are going to be in pain. C compiler analogy again: I can use an IDE to shield myself from these issues. The beauty of Git is it's got such widespread support there's so many great tools, and I honestly think you would be "mad" to pass them up.
> I especially see it when somebody not from my background is approaching this.
Like who? Git is a tool for managing code. I think he might be driving at non-programmers who contribute to a project like graphic designers or people providing copy. Fair enough, but that's an extension of the brief for software VCS which is primarily designed with managing and versioning text-based software ... it's not, historically what they are for. Surely there is software for managing these kinds of assets?
> I will get you to think about a directed graph or as > No human thinks about that
I'd say a large amount of people on here think like that. All are human. But facile analysis aside, most people that use git don't talk like that or describe what they're doing like that. The "chain of commits" is a very useful mental model however.
> I’m gonna save my work and I’m gonna share it with other people. Then I’m gonna step off this computer and just leave for the day.
Yes, you can zip it up and email as an attachment, or export it on Dropbox. But when you need to store your changes "on the record" it will need to go into a version control system at some point.
> I feel that version control systems (the next version of them) should not be something that was specifically made for the Linux Kernel community
Literally any other existing version control software. Check out mercurial for something that approaches parity with git's features [1], it was an early frontrunner but Git ran away with it globally. Nobody was forced to use it, it was just the better tool.
[1] https://www.joelonsoftware.com/2010/03/17/distributed-versio...
‘commit’ will take a snapshot to your local branch. But then, you have to “push” it to the remote branch.
I understand what it’s doing, but the choice of words seem wrong. It sounds like “push” has a lower importance than “commit”. But because “push” will sync your local changes with the master remote system, then this obviously has more importance.
Instead, I think they (Linus) should have used something like “snap” for snapshot, to take a snapshot of your local changes. Then “commit” would be used to push your local changes out to the remote server or repository.
/thread
It's pretty telling that there have been multiple attempts to write a saner CLI for Git.
A free market theory says anyone can prosper if one does what can do great. Do something else. Learn git. Or drive trucks. Do not complain.
“Started using git when GitHub was in beta” what a newbie haha.
Saying that git’s distributed nature makes things harder - well it’s the entire nature and point of git to be distributed :)
People don’t want simpler, friendlier source control, this is why bzr failed and was abandoned.