The underlying technology of git is great, but the UX is terrible. The commands are all named wrong. "To create a branch, use git branch, but that doesn't check it out. If you want to create it and check it out at the same time use "git checkout -b", not "git branch --checkout" which would be 1000x more logical (and then there could be an option to make that the default behaviour)
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 don't think memorizing commands is really the problem. Learning just 8 git commands (clone, pull, checkout, checkout -b, commit, push, merge, rebase) will cover like 99% of situations average dev will ever encounter. And when you need something more exotic you usually can google it, usually in under 5 mins.
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...
You forgot log, cherry, stash, blame, which are also daily use commands. You also have to learn a lot of concepts to even understand the help and error messages for these commands - the worktree, the index, the stash, HEAD, ours vs theirs, conflicts, remotes, tracking branches, when it is safe to push -F, etc. Depending on the project you joined, you may also have to immediately learn about git LFS, submodules, squashing, fast-forwards, tags.
You have to understand a lot of things before you can somewhat comfortably use git, much more than something like P4.
Based on my experience - most teams will get by with ivanhoe's list.
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.
As I said to the other commenter - I don't even know how to use git without the stash, since you need everytime when you have some local changes but want to pull from the remote - the only alternative I know of is committing your local changes instead of stashing them.
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.
At work I have 30 stashed things some of which go back 2 or 3 years. I got distracted when I pull and forget to pop sometimes, or I was working on something so trivial I never unstashed it.
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 I said to the other commenter - I don't even know how to use git without the stash, since you need everytime when you have some local changes but want to pull from the remote - the only alternative I know of is committing your local changes instead of stashing them.
I usually do all the work in branches anyways, so I'll just create a quick branch and commit it there.
> I 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.
I've used both but generally don't use stash. I think it's more expressive to have a single commit like "wip: some simple description goes here" and then to `git commit --amend` this until we are happy with its contents.
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.
Tip, instead of amending, it's also straightforward to "uncommit" a temporary commit when you come back to it. `git reset HEAD~` and the state of the commit becomes the state of your working tree instead.
You can set `merge.autostash` and/or `rebase.autostash` to `true` in your global git config and then you can `git pull` with a dirty working tree.
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.
That's one more confusion vector. I for example use Git for like 10 years now and I didn't know about this option. It didn't even occur to me that it could exist.
It might help creating patches for the dirty state with something like `git diff > feature.patch` and then drop the current changes. After update, it's another `git apply feature.patch` to restore the changes.
This helps with remembering what each change means since `git stash show` is rather awful. YMMV
git fetch && git rebase origin/master, which is equivalent to git pull --rebase origin master, requires your worktree to be clean, so you must either commit or stash if you have any local changes.
I think that's a very good way to have a long list of things stashed that you don't remember what they are.
Commiting your changes is much better as you can add an explanation for your futur self.
Ok, so you don't need to know git stash (good) but you need to know that autostash exists and how to configure it, so you still don't get away without an extra concept. I suppose the nice part about autostash is that it's easier for someone to just give you a .gitconfig with it, and not have to teach you how to use git stash.
The `.gitconfig` and also be 'given' to you by just being checked into the project. Someone has to know that you can have per-repo configs, but not everyone. ;)
> I think there red flags if they are needing to jump into stash, cherry, etc on a daily basis.
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?
> I think of log, cherry-pick, stash & blame "quarterly use" commands
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.
How can you pull without using stash? Do you always commit everything before pulling?
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).
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 use git pull pretty frequently. I like to keep my main branch up to date with the main branch of the remote repo. I find it's helpful to have that consistency across contexts.
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?).
There are few differences between "local" and "remote" main in GP's example. "origin/master" is a _local_ copy of the origin's master branch, and updated with every "git fetch". So "git push origin origin/master:master" resolves the "remote master was deleted" without having to stash/checkout/etc.
It's just a preference thing. If I'm sitting down to write a new feature I can do the git fetch origin and go directly to a branch, but if I'm investigating an issue, I'll often open that develop/master branch directly, find the problem, do a pull to make sure there are no changes that got checked in, then "git checkout -b".
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 basically never use git pull. I use git fetch and then I check (using git diff, git log or in confusing cases gitk) what I want to do. That could be merge (fast forward), rebase, ignore or either branch because the other one is just better. Of course often pull might do what you want, but when it doesn't people start to complain. So better avoiding surprises from the beginning.
It sounds like you finish your work much faster than I do. I usually go for the same workflow as you do, but it can take days between a branch being created and the moment I'm done with it. During this time, I often want to keep up with the latest changes on master. Other times, more than one person works on a feature branch, so they still need to git pull from origin/feature-branch into feature-branch to get the changes from the other committer.
I would be very happy if I could just merge to master every day, but that is extremely rare for me and my team.
No, I don't necessarily work any faster. But I will switch between multiple feature branches as necessary. And to keep up with master, I'll rebase my feature branch onto origin/master or depending upon the circumstance I'll directly merge origin/master. Both keep me up-to-date without a direct pull.
Well, if you're switching branches, you already have problems with a dirty worktree. Also, pulling can actually mean rebasing (I always use pull --rebase).
My team works on feature branches that get merged to master. Only master ever needs a git pull and you never work directly on master. Every team I've worked with over the last ten years has done some version of this work flow with small deviations.
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.
I almost never use `git pull`. I have a helper script (written by an ex-coworker's father ...) that fetches + updates my master branch head to the proper place, without changing away from my current branch.
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.
It sounds like you're using a very different and much more complex process than average. Keep in mind for a lot of web projects releases are every day, sometimes multiple times per day.
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.
For our project, a flow like `create feature branch -> implement -> push -> review -> merge to master` is rarely something that finishes every day (but there are daily changes to master from someone else on the team). Builds are something that happens for every change to master, and there is constant QA on those builds. Even if we chose to release those builds to customers, the question of "did a fix for bug X make it into build Y" would still arise quite often.
Yes. Doing a “git commit -am savepoint” on a feature branch is not a big deal; it will get folded into the squash merge with everything else in that unit of code review.
If you have a dirty worktree, `git pull --rebase` fails. You need to either commit or stash your local changes. To stash them, you can use git stash. If you decide to commit them, that's ok, but then you also need to learn about `git reset --hard` or `git commit --amend` or `git push --squash` if the changes were work-in-progress.
So which would you recommend?
Oh, there is also the option of enabling autostash I think, but that is relatively recent (maybe 1 year?)
If you have to pull while your work tree is dirty, it’s best but not easiest to branch & commit (safest and avoids the possibility of conflicts during pull), or commit & pull with rebase (safe but might have conflicts).
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:
It's interesting that you mention branching, because that is another workflow where I feel that I constantly have to reach for stashing - when I simply want to move to another branch (either for a quick bugfix or simply to check something).
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...
It might be worth really picking apart why you think you need to stash instead of commit, and why stash feels easier. I honestly don’t think committing is any more work than stashing at all, not even more typing. It’s really not more difficult to commit what you have temporarily, go to another branch to work, then come back and continue working, compared to stash. But I don’t doubt that it feels more difficult for some reason. Is it the need to make a commit message that causes the mental friction? Does git reset somehow seem tricker than git stash pop? Think about how you typically rebase when you’re done anyway, so that means when you come back to a branch with a temporary commit, you don’t have to stash pop, you can just add more changes and squash or rebase it all later. With the stash workflow you have to keep the stashes in your head, and manually pop them. They get harder to manage than branches when you have multiple stashes, since they’re disconnected from their context. Personally I think if you examine what it really takes to use commits & branches, and practice using them more, you may find it’s just as easy as the stash workflow, if not easier, and it comes with a wider safety net and is easier to manage when you have a lot of different changes in flight at once. I also think it helps to realize that a branch is nothing more than a named SHA, they are incredibly lightweight, and using them ought to reflect that.
I think it's primarily a question of focus: I want to pull or to switch a branch. The fact that I have to do something like committing or stashing is already an annoyance - having to come up with a commit message is even worse.
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.
You can, if you want, git fetch without committing or stashing, and then checkout just the files you want to update in your work tree, as long as they’re not the files you’re working on.
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.
Well, you get rid of the need to know git stash, but now you need rebase -i, amend, the idea of squashing, probably git reset if you're not happy with a commit... Whichever way you look at it, you need to learn quite a few more commands (and concepts!) than what the initial list claimed.
Cherry-pick probably depends on what kind of software you're working on. If there is alway exactly one version in production (two if you deploy gradually), then I don't see it being needed often. If you are supporting multiple versions at once, then it ends up getting used just about every time you have to fix a bug.
We also use it very often when we approach a release - usually there is a release branch that gets cut from master, and then for a while you have in parallel features going to master and bugfixes going to master and cherry-picked to release.
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 think I've used `reflog` maybe... twice in a decade of daily git use. It's crazy to me that anyone would think that it's a daily use command. I don't even know what bisect is off the top of my head.
I don't use `reflog` often but I've found that 9/10 times you make a serious mistake in git, it ends up being the go to solution.
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.
Bisect is a debugging utility - it helps you do a binary search for the commit which introduced a bug by checking out code at certain commits, having you compile and run it, and tell git if the bug was there or not, and then going back or forward in history until you can identify the 1 commit that caused the bug to appear.
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.
Usually, I prefer to investigate a bug starting from the code rather than the history, if it's possible. In my experience, most bugs have taken longer to reproduce repeatedly than to understand from code. Besides, there's no guarantee that a bisect will land at the right commit if the bug is not reliably reproducible.
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.
P4 definitely has its own rough sides, but I find the model is overall much simpler.
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.
From CLI, p4 is pretty consistent - rather more so than git (which I suppose isn't a high bar!). But of course there are some inconsistencies - as with any tool, particularly if its been around a few years.
Small frequent commits will limit the need for stash. That's a good practice anyway.
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
Why is small frequent commits a good practice? What is to be gained from committing a change to a file, then a commit to undo the previous one if you decide the change wasn't useful/needed?
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.
The most important reason imo is making code reviews easier. Enormous PRs = less confidence in merging code on a team. If you are pushing small commits then it is easier for the team to follow the changes and review them.
- 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?
All of those only make sense to me if a commit is a finished work item. If I'm committing just because I want to switch branches or pull, most likely what I'm committing is not meaningful in any way. If I squash later, it doesn't really matter, the reviewer will see one commit anyway, so committing often or not didn't help.
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.
One benefit of frequent commits is that it allows you to go back to a recent commit in case your code gets screwed up and you want to undo some recent changes. For example, if you do a search/replace in hundreds of files and make a mistake.
> What is to be gained from committing a change to a file, then a commit to undo the previous one if you decide the change wasn't useful/needed?
"Undo" commits make sense, occasionally, to fix recent incorrect or improper changes that have been already pushed.
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.
You don't have to "understand" it. Just form a basic opioun of what you think they will do and build an experience of what usually happens. That is what I do anyway as a software developer for 8 years.
I really really disagree that you need all of those. I have been using git for several years and never used blame. I use built in IDE tools to view revision history. I occasionally use stash, never use cherry, never use log.
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.
The problem is not the 99% of situations that you can memorize, but the 1% of times when you realize you have made a mistake and strayed from your beaten path into the dark scary unknown Git woods where monsters with detached HEADs may be lurking behind every tree, and you have to ask a coworker or StackOverflow to rescue you...
Reading TFM and understanding TFM are not the same thing. The more intuitive the design of the system, the closer they are. The point people are trying to make here is that git specifically has an uncomfortably large gap between the two.
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.
I have read the manual many times. But when I only run into an issue once every 6 months to a year or so, its not exactly fresh on the mind. I still like to look it up again, to make sure I'm not working wrong from memory, and about to lose my work.
So you agree that you should Read The Fine Manual when you hit unfamiliar territory? My post wasn't aimed at saying git isn't complicated, but to encourage reading the thorough documentation of the tool giving you trouble rather than immediately shutting off the brain in the face of unfamiliarity.
TFM is often extremely vague in my experience. I always start my journey into the git haunted forest with RTFM, but I almost always end up on Stack Overflow looking for confirmation that commands actually do what I think they do.
Many have and still don't feel comfortable with their understanding. And there's too many of them for inadequacy or incompetence to be a useful explanation.
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 think more than one thing can be a problem. The CLI is confusing and the model is complicated. This means people can get themselves into weird, hard-to-debug situations. Or end up copy-pasting incantations in hopes of fixing problems, but instead might lose their work.
I've never seen a scenario that resulted in a developer losing work. You can always retrieve things out of the commit history, even in pathological situations.
Part of it is feedback to me. The timeline view in most Git Apps makes it super clear to see where you are and where you can go. Starting out in Git with an established repo is like driving at night without headlights.
Even though naming the commands might be arbitrary choices, they can be practiced upon. One doesn't always have to fall in the semantic trap.
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.
You need to use either merge or rebase, or git won't allow you to push. Also, pull doesn't modify your remote tracking branch (origin/branch) - fetch does that.
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).
I was going to negatively answer your comment until I remembered that I have had [pull]rebase=true in my config for almost 10 years, so it have always been the "normal behaviour" to me. I never looked back to this.
So I agree with you, the default pull behaviour that pollutes the branch with useless merge commits is plain stupid.
When I first started writing software I would often rewrite third party libraries I didn’t understand to reduce complexity.
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
Of course. You must be allowed to fail. Times have changed, and I can’t imagine what it’s like to be a new developer now. Perhaps the drive to be social and show off your work is the part I can’t understand.
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.
> learning git took a lot of trial and error, but now whatever terminal I sit down in front of
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.."
Agree with you. A GUI is fine (and a good thing) as long as it is just for convenience and discoverability, and it doesn't abstract git away, hide its power or try to impose its own workflow.
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.
Yeah I heavily recommend magit to anyone who can tolerate Emacs (which is unfortunately a barrier). It's allowed me to discover so many powerful Git features I would otherwise never have used, and provides a very intuitive interface that does exactly what you expect it to do. This is especially true of its wrappers for rebasing and history editing.
As well as smartgit, I only use it for squashing and merging stuff but it shows nice output so I guess you can learn the commands from there doing other stuff as well when you're starting to learn git.
I think viewers like gitk or tig, or more powerful tools like magit/sourcetree/etc. when used purely to see your repo's history, are not only acceptable but are the quickest and most intuitive way of understanding what's going on. I'd hate to be restricted to `git show --oneline --abbrev-commit` or similar commands that don't show branches and merges.
Writing a new git GUI doesn't solve the problem, since you need people to adopt it before it's widely installed as default on most OSes by default, and until then you'd probably need to learn the old interface anyway.
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.
I contributed inconsequential things to Gitless for a very short amount of time years ago. One of the things that I really liked that I ended up rewriting at home was better highlighting, eg inside-the-line level highlighting like github etc. Also maybe it had native support for vertical split? Either way my at-home added that.
No idea if that's still in gitless or if anyone else feels that way, but if I'm gonna live the cli life may as well make diffs comfortable for myself.
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.
The biggest hurdle I had to learning Git, if truth be told, was my own aversion to doing anything that wasn't easy. It seemed difficult, so I dug my heels in and say "No! I don't wanna! It seems like friction and that's too hard."
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.
We have no choice but to "get over it and get on with it". But it DID NOT have to be that way, and that's what makes many people keep their resentment. It's like a kind of "hazing" experience.
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.
Ugh... the visual studio integration is HOOOOOORRRRRIBLE. I hated it. It didn't do anything to make my life easier.
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.
For recent versions of git I'd suggest using "git switch" and "git restore" instead of git checkout.
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.
> The underlying technology of git is great, but the UX is terrible.
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.
I get what you are saying, and this makes sense, if you are in a situation where the problem your tool solves is so special and the target audience of your tool so involved that it makes sense to do things differently than the rest of the world.
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.
> Think about vim: it is cryptic, does everything different than everything else out there , but it gives you something in return.
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.
It's not just the UX. It's the concepts the user has to understand in order to use git (without shooting their feet off or consulting a guru frequently).
If you use UX purely from the concept of User Experience, then failing to understanding the concept of something is a failure of UX.
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.
This clearly isn't a popular opinion, but I may as well add it here: I like git. It's not that bad and not that hard to use. Occasionally I have to look up how to do something, usually involving git-filter-branch. But that's no surprise, because what I'm trying to do is usually inherently complex. I don't think a different interface would solve that. For most other stuff, git is simple and easy to use. It was a bit slow to learn, but most really good tools are (e.g. vim).
I think that's unfair because I don't see that git even has a UI - it's designed to be a command-line API. The thousands of terrible GUIs out there are so bad that using the command line directly is still the best UI. (I think GitHub has done a great job managing remote repos - I am only talking about local tools.)
I don't think Git has a "terrible UX". It really is no less worse or better than any random CLI program.
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.
checkout -b seems more logical to me, but not even close to 1000x more logical. Whether it should go on branch or checkout is just an opinion. You're blowing some tiny disagreement up to ridiculous levels.
I actually dislike Git profusely but these arguments are very, very poor. git checkout --branch vs git branch --chekout ? Depending on how the wind blows I could see myself leaning on one or the other. WHO CARES? This is not even a paper-cut level of annoyance.
Kraken is the first UI that I've found that makes editing commit messages on previous commits easy. I spend an inordinate amount of time moving hunks between commits/etc in order to present a "clean" git log for a couple opensource projects i work on that have OCD maintainers.
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...
I was on the GK team a few years ago, so I'm obviously biased, but I believe that GK—specifically the design of graph[0]—helped me a lot to level up my git-fu.
[0] which was created before my time at Axosoft, so I'm not that biased :-P
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.
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.
I wish it wasn't coupled so tightly to emacs but magit is a phenomenal gui for git even for the more advanced use cases. if you know vim then spacemacs wraps it up in a more palatable package.
I've tried GUI interfaces to git before and I just haven't been satisfied by any of them. They seem to work right until I need to do something out of the norm. I did find git a huge PITA when getting started though but now that I have some muscle memory, I won't be trying anything new any time soon.
For Git clients in particular, there's the issue of GUI applications that think their mostly ad hoc, incomplete configuration should prevail over standard Git configuration (e.g. GitAhead is unable to use authentication tokens on Windows) or that their "opinionated" behaviour is good for everyone (e.g. try to modify a tag with SourceTree).
I've used git for ten years, at half a dozen organizations (I'm a consultant/contractor). I have accepted that it's what we use now, so I use it. But...
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.
Reading all of these threads, I think the conclusion is: we still haven't figured out how to do revision control in an intuitive way, because it is highly nonlinear and our brains just don't work that way. There isn't a clear vocabulary for intricacies of revision control, yet. And if you can't name something clearly, you can't explain it clearly.
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.
> 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.
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.
I know this sounds boring, but I enjoy looking at how programs manage command-line options. There are so many libraries in many languages. Some require structures so that help screens can be autogenerated. Some allow grouping of options `tar xvzf`, some don't require a dash, some have one-dash for short and two dashes for long options. Some require `=` between parameter and value, some (like mbed, npm, yarn and git) have subcommands and sub-subcommands.
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...
Python an interesting example because, as the BDFL has ceded more control over development to others, it has been gradually losing some of that consistency.
> 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.
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.
What do you recommend in these cases? People in non-technical fields often ask me about collaborative software, "like google docs, but for non text files". My mind goes straight to VCS, but git is too hard to get them quickly up and running.
I tried SVN one time, which is a little simpler, but still didn't catch on with the person I was showing it to.
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.
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.
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.
>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.
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.
I think you're twisting the problem statement a little here.
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.
I think you're missing the forest for the trees here. The point of version control systems is to make developing software easier. It's a tool that exists for the convenience of its users. It's reasonable for people developing software to ask for the ability undo a change or restore a repository to the way it was a second ago. Telling a team of people using Git "it doesn't work like that" is unhelpful because it's not impossible for a version control system to work like that and the point of any software is to help them do what they're trying to do.
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.
> But there's nothing holy or fundamental about an implementation detail of how Git does things that makes their use-case hard.
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.
VCS exist to make it possible to organize and track changes to project source code. Convenience of the user is a secondary goal to clear organization and code management.
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.
I don't think that last bit is necessarily true. Git has strong network effects, and people are generally very conservative about tools like source control. Git also has the benefit that there are a lot of people used to its quirks, and that skill investment makes them feel fond of it.
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.
> I have to laugh when you say its replacing email.
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.
I have no problem with using Slack or Hangouts or Discord or some other chat solution while at work. I also tend to use discord/steam for throw-away conversation with friends.
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...
Ok, this one is entirely fair, but also I'd argue the circumstances around it are a little different.
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.
> 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,
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.
You can’t unsend an email because you can’t force someone else to delete something. Emails end up as files on someone else’s server. Claiming this is a UX issue is intentionally missing the point. If this is legitimately a foreign concept to you, an afternoon setting up postfix and playing around with it might be worth your time. Email is a protocol, not a program. A “delete” request would be just that, a request.
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.
> Emails end up as files on someone else’s server.
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.
Thanks for the explanation, but I ran mail servers for ~25 years. I am familiar with the technology, and in the mid-90s even wrote a chapter of a book explaining email. And I've been using version control even longer. Maybe try rereading what I wrote without the assumption that it comes from ignorance.
I think your comments are coming from ignorance, though.
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?
I have in fact never said "I should be able to unsend my email". Once. In my life. Please try to argue with my actual points; I don't have time for straw men.
>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?
Yes, I am indeed accusing you of a strawman. You seem very much in the discussion to win it, whatever that means to you. I can only hope that, having decided you are victorious, you'll now leave me alone, because none of your comments seem particularly productive to me.
>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.
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.
That's a plausible reason, but it's definitely not what the person I was responding to said. "There are user reasons that won't work," is a very different answer than scoffing that the person asking the question just doesn't understand the underlying technology.
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.
>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.
Technically, I think their problem is assuming that it's acceptable for there to be such a entity, not that one necessarily exists. And then misinterpreting/misrepresenting git's semi-intentional exclusion of such a entity as a bug when in fact it's a feature.
I'm not sure that that such an entity is truly necessary to get a lot of the functionality. However, in the case of git, I'd guess 95% or more of users in effect do have a such an entity. Github is $7.5 billion worth of proof that most people are cool with effectively centralized source code management.
> 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.
If you try to do that too hard you run into the task automation problem:
I don't see what it's got to do with github. I had the same need, and the same confusion solving it, before I had ever used github, when I used a locally hosted git server of some kind for my team.
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.
They're complaining about git and the very first thing they discuss is how git interacts with a completely separate piece of software. Push doesn't have to be to Github, it can also mean sending an email. Obviously you can't undo that.
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.
OK, I understand you think the way most actual use of git I have observed takes place is "the wrong model to have". That is an opinion you can have, and you can try to convince people of it; to be succesful at doing that, you probably want to understand what motivations and pressures lead to this style of use in the first place; why do you think so many (from my view, the majority of git users), choose to use git in this "wrong" way?
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.
It's not specifically github, but I believe this wrong mental model was greatly popularized by it. Until GitHub rose to fame a project had reasonable chances to pick mercurial, or sometimes SVN; today the default is git on GitHub. That is the issue: when you choose a tool not because it's the best at what you want to do, but for other (very good) reasons: it's popular so you'll find help easily, more people will interact with you, etc...
So, no, GitHub didn't create this, but it made it default
sure, but that 30s timer is an incredibly useful feature, when you misclick, when your cat walks on your keyboard, when you remember that you forgot $RANDOM_THING, etc etc
This only works because you can configure gmail to send email on a timer instead of immediately.
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.
If you were before the github, you would not expect an ability to un-push changes. If you were doing development back then, you are likely familiar with "ftp" (or maybe "sftp") and using it to upload files. Or maybe with CSV or SVN.
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.
Right, it's also because github guides people into a history-only flow instead of rebase / force-push. Casual github users know they should follow the tree with pull and don't know what fetch is.
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.
I spoke to a person that didn't like rebasing who said that the threshing didn't matter because nobody reads the history. But for me it's one of the first tools I reach for when I find a bug or confusing code, trying to understand the intent. I see that as a fundamental difference in how the problem space is viewed and that they're stuck with a Github-first point-of-view. To me, even with merge commits, the history should be a statement of intent and treated as a first-class citizen, or even the primary output. Pushing a branch with threshing is like sending an email with visible backspaces.
Completely agree, a change is an atomic change and should be contained in a single commit, I don't need to know the sub-steps it took to arrive at the final solution when I'm trying to blame or log the reason it changed 6 months from now. It also encourages bad commit messages which further confuse change history and motivation when you're creating separate commits just to fix formatting and such in your real change.
I have been using git for years, and have never rebased once. I'm kind of scared to try, perhaps irrationally. Rebasing seems to change commit relationships in a way that seems like it may be difficult to untangle if it later differs with someone else's clone.
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.
Is there a reliable way to know whether any of the involved commits have been pushed anywhere? I would probably usually know off the top of my head, but not always.
> I spoke to a person that didn't like rebasing who said that the threshing didn't matter because nobody reads the history. But for me it's one of the first tools I reach for when I find a bug or confusing code, trying to understand the intent.
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.
It's not about the object database, it's about what you see with git log.
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.
Mercurial has solved this quite elegantly. The Evolve extension is basically standard functionality and all changesets (commits) have a state: secret, draft, public. You can share the changesets and you can "prune" them, which basically tells the world that if they have a changeset with that hash to delete it.
> If you don't know what git push means, you shouldn't be using it and are playing with intellectual property fire.
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.
Not just Github. Having any GUI be your first interaction with Git is a disaster. Right now the only way to learn Git is via book or man page, and command line. All the decent GUIs I have used assume you already know Git. They are great and powerful, but they don't help at all with the onboarding process. If you know of one, please share. I had to stop using GUIs completely and learn with Git command line. Then the GUIs made sense.
Rather than a problem with GitHub, I think it's more just a problem of dominance. Git was originally designed for a work environment where people weren't on the same network, or any network at all when making code edits. At the same time, everyone wanted a copy of the history that they could change themselves to mirror their work. So we needed a tool which could be distributed, not require a regular network connection, and still enable people to share changes and view the entire history of a project.
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.
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.
I use Perforce everyday since it aligns better to the needs of the games industry.
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.
I’ve had to use perforce before and was not a fan. Granted, I didn’t have to use it full time and can’t claim to be an expert, but I hated the notion of locking files, change lists, yuck. All of it felt so clunky compared to git.
Funny - I used P4 for about 7 years before switching to Git 2 years ago, and Change Lists are what I miss most from P4. For me it is extremely common to work on multiple changes in parallel, on the same branch or different branches, and organizing my changes in different change lists was the best way to handle it.
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.
Locking files is critical when you are editing binary data which can't be merged - which in the games industry, is generally how the majority of the dev team works.
I’m not sure locking files is as important as all that. You “check out” files, but nothing prevents anyone else “checking them out” (which is perforce parlance for: “make editable”) - conflicts can be resolved.
There is locking but it’s seldom used- handy in the gaming industry for code which depends on data.
As cecilpl2 commented - it's the typically the binary art assets (occasionally other files) which are unmergeable which need the exclusive lock turned on. And of course you want to avoid branching those too in many cases.
Never used it but I had to use ClearCase at work even though I was already proficient in git.
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
At my current job, I had to create a command-line tool just to be able to checkout things from perforce. It is ridiculous how difficult the UX is for this. And companies are still paying for it!
Not just that, they seem to suggest Github created Git...
> 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.
What other structures would work for having a public forum for PRs?
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.
They could have added namespaces to branch names. Right now branch names are just a free-for-all. Instead, if they insisted that branch names are always prefixed with "username/", then you wouldn't need forks and anybody could freely submit code to any project. PRs would become MRs.
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.
I think we're all still dancing around a blind spot, where we want eventual, Pareto Principle consistency (where a consensus is formed around 10% of edit histories, many others require only a consensus of 2, and the rest are backups that require a consensus of 1)
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.
> a system that knows it's connected to other people, where changes are instantly propagated and easily visible
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!
I don't understand the negativity. I'm not saying that git is bad, or that git sucks. It is what it is, and not wat most of the people really want.
> 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 ?
The negativity, I feel is on the part of this whole critique. A bunch of guys came up with a tool for themselves and it turned out to be so good that it not only took the software development world by storm, but it pretty much killed all competitors stone dead.
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 ...
While the above is tecnobabble, there /is/ a simple way to state what git is. It's an API to interact with a torsor.
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.
How is this any less technobabble? I looked up torsor on wikipedia. I learned nothing, except that "torsor" is a real word, and not just something you made up for a joke.
How could you possibly not have learned anything by reading the wikipedia page for "torsor" that starts with the following?
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.
While this sounds all nice it actually fails to model Git as it is. Git is an object database and its objects are blobs, trees and commits not diffs, so your premise is based on a misconception.
Git itself requires you be able to think of it as both models, diffs and snapshots. For example most uses of `git rebase` are clearer if your mental model while doing so are of diffs.
That only one is how it's implemented is besides the point really, until you get _quite_ low level.
Of course when working with Git it makes sense to think in changesets. But OP was specifically modelling the technical side starting with "We have files, which are inert objects …".
And that's a bigger problem with git than the horrible commands. Every project I've worked on that has used git has had a diff-based workflow, and sometimes the mismatch is painful — I wish I didn't have to know about `--full-history` and that `git show X` isn't necessarily the same as `git diff X^..X`.
A "commit" doesn't contain a diff, it contains (references to) the blobs of the files at that state. Diffs are display-only, generated by comparing two full file states.
You really believe that git stores -- in full -- every version of a tracked file? Every commit that deletes the whitespace from an otherwise empty line in a 30KB file is another 30KB of hard drive space gone?
> You really believe that git stores -- in full -- every version of a tracked file?
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.
> "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
Isn't it the case then that git doesn't store in full every version of a tracked file?
git does perform delta compression. From what I can gather, git's storage engine uses conventional compression (zlib), deduplication (exactly identical files need not be stored twice) and delta compression (between similar files).
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.
The git book explains the internals very well, so you can easily verify it for yourself. Files are referenced as objects in trees, which are pointed to by commits. editing a file creates a new object for it. (edited for tone)
> 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.
That's just for compression. Commits aren't diffs, and when you checkout stuff, git doesn't do diffs to give you the working directory at that point. See https://stackoverflow.com/a/25028688/8272371 for detailed explanation.
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.
What you are missing is the difference between gits object model (with loose objects) and packfiles. The delta compression happens when you run `git gc` (git does this automatically as well on occasion), and packfiles is how git fetches and pushes history.
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.
Everyone here is arguing past each other because one side defines "what git does" as the literal implementation details of git, and the other side defines "what git does" as the model it presents to the end user. I suspect the reason for this disconnect is partly due to the emphasis on understanding the "internals" of git and the fact that this is about between the internal implementation as it exists in code and the internal model/interface.
When git makes packfiles using delta compression, it ignores the history. It roughly sorts blobs for similarity, completely ignoring their filenames or which commits they appear in. This sorting helps to make the packfile delta compression more efficient. The deltas on disk are completely unrelated to the diffs you see from `git show`.
Which is explicitly a lower-level optimization applied to files well-suited for it and not related to the concept of a commit. A commit does not reference a diff.
Fair enough. The blob stores a diff. The commit stores a reference to... the diff. This is a division between the concept of the object and the implementation. But it's not an example of a diff-storing model failing to model git as it is; git as it is is storing diffs.
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"?
Each commit consists of a structured collection of hash IDs for every file in the entire repo. The hash ID is generated by hashing the contents of the entire file. Not the diff.
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.
And that's part of the problem with git! It requires you to get a mental model of how it works internally, but only part of how it works internally is important, and there are terminology conflicts. So people get incorrect ideas about how it works, then get surprised when something unexpected happens.
There're revision control systems based on diffs, but git's power (and durability) is that every commit references only blobs, which are (content addressable) files, not diffs. All the diffs used in git log presentation or git-diff command or git rebase command are computed on the fly from the two stored versions. And yes, if you commit a giant file, and then delete it in next commit it's there forever, until you remove or rewrite a history of a branch that references this file somewhere in history.
There're optimizations on the storage level, compression etc, but on logic level those are transparent
I would understand "a commit is/contains a diff" as the commit referencing the difference to its parent commit(s), whereas in a packfile the diff might be against a blob belonging to an entirely different branch of the repository, if that's a better diff. Which might be different for each file. And the blob doesn't have to be a diff, it only is if the packer found a good candidate.
If it didn't, then the diff mechanism git would end up using would be purely internal to git and abstracted away for the user. Why? Because it would mean your diff algorithm is now your storage format and it is not allowed to change, ever. That's going to cause worse issues than large git repositories.
There is also the obvious performance problem that you would have to replay all diffs to get to switch between commits.
It does, yes. To add a bit more color though, what happens is that when you run `git gc` (or it's run automatically for you sometimes) an extra compression step is done that uses diffs of some sort to avoid storing so many near copies. Packfiles are related to this.
git works off of snapshots which are blobs, and blobs are compressed very effectively, but if your file takes 30KB compressed then yes, 30KB compressed is being added for every white space added[0].
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.
Oh my yes. Some years ago, I did not realize this. My mental model of Git had it de-duplicating common text between commits, but this is not the case. I learned the truth the hard way when I wrote a commit hook that automatically appended about a hundred lines to a text file with every commit. It worked fine at first, but eventually `git fetch` started failing.
A diff is something that describes the changes between two versions but does NOT refer to any specific version; or at least it is something that can be worked with independent of any specific version.
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.
While this is a wonderful explanation for a person already familiar with mathematical concepts such as groupoids, torsors, and directed acyclic graphs, I think that this explanation is really unfriendly for the layman/novice developer who's just trying to get their changes up on Github.
All is well until you need merges, which is where the confusion happens and minds are lost.
- 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.
Ah, so just a file space with a rooted DAG where each node is a diff with paths manipulable by queries where diffs can use a groupoid action to produce a new file or conflict, resulting in an API to interact with a torsor.
This is funny but I think it strikes at a real truth: what Git is trying to do is legitimately difficult. I can see where the author of the article is coming from and I agree that Git has a lot of commands and it's hard to pull it all together, especially if you are new. And I agree that these commands could be better organized and presented and I think that's something the project is actively trying to address.
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.
Mercurial shows that it's possible to hide much of that complexity behind a user interface that only exposes as much of that complexity as necessary.
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...
git is a fast, content-addressable, decentralized and symmetrically ad hoc synchronizable, cryptographically verified filesystem, stored as a directed acyclic graph of tags, commits, trees and blobs, in that order, with SHA-1 pointers as edges, backed by a POSIX filesystem, with both a simple storage format and a space- and seek-efficient, compressed delta chained pack format.
There's also very little in a graph of changes and revisions that could be considered a manifold, which makes looking for homeomorphic endofunctors pointless.
But the first impression is strong, it's still a good joke.
I don't agree at all. Git is the simplest version control system I've ever used. The concept of merging, rebasing, cherry-picking, and resetting works so naturally that I'm basically going to expect this level of ease of use from any VCS I use going forward.
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.
>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.
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.)
I fully agree that the default porcelain has poor UX for managing the staging area, but doesn’t a porcelain without it encourage overly large commits?
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 ;)
> porcelain without it encourage overly large commits?
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.
You can do the same with git stash, but it's also inadvisable because of how easy it is to lose changes. My workflow in this case is to checkout a new branch and commit the work-in-progress there, then switch back to the previous branch to check the commit. I've seen numerous pre-push scripts that do exactly that.
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.
> 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.
Thinking about it, I guess it should be possible to flip this around by using a temporary local branch. Commit everything there, then cherry-pick into repo dir and commit proper.
> I fully agree that the default porcelain has poor UX for managing the staging area, but doesn’t a porcelain without it encourage overly large commits?
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.
> 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.
That sounds like a personal discipline problem and not a poor tool.
That's like claiming a gun is just used for shooting other things and that the point of the gun is so you don't have to understand how to handle it. Then when you shoot yourself in the foot you get mad at the gun and not yourself.
Guns are expected to be drop-safe. Some people say "well you shouldn't be so careless with a lethal weapon anyway", and yet most people will want their gun to avoid firing a bullet when dropped.
That's how you get good commits... you do a bunch of changes to understand what you should have done and then you retell the story by carving it into commits. I have been doing this constantly for like a decade now and almost never "give up"... in contrast, Subversion, which doesn't have a staging area, is almost impossible to use as it requires you to somehow code in order the first time, which is ridiculous: no one is that perfect.
> But that flexibility adds an extra cognitive burden when a newbie just wants to save a "backup snapshot of the repo".
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.
When you're writing into a text file and then save it, you don't have to manually select what lines or pages you're saving - you're saving all of it.
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.
When you're writing into a text file and then save it, you don't have to manually select what lines or pages you're saving - you're saving all of it
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.
> When you're writing into a text file and then save it, you don't have to manually select what lines or pages you're saving - you're saving all of it.
I don't understand the point you're trying to make; this is just as true of the command I gave.
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?
Buzzkill! I think it's more a matter of that those who are in a position to do so are used enough with git-cli that they are happy with the status quo.
> Even though I grok git's mental model, I still can't answer the top-voted "git" questions on Stackoverflow without a cheat sheet
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.
For 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.
I feel the same way, I understand git pretty well but cannot for the life of me use the CLI. Fortunatly there are some pretty good GUI around, I personally use GitExtensions and find it suits my brain nicely. Its windows only though, not a problem for me since my work forces me to use Windows and I don't code at home but surely they are nice git GUI for Linux no ?
Totally agree on the "staging area". I've always thought that the staging area should only activate when you `git add` or otherwise add files to it. If there are no staged files, then git commit should act like git commit -A.
Oh hell no, Visual Studio has this behaviour by default (commit all changes if nothing staged) and what we end up with is that some people keep checking in various experiments and privately modified launch config files (that should not be in the repo anyhow but that's another story related to the tools) that end up causing a lot of unnecessary merge conflicts when you pull in their changes (where you were really only expecting some other part).
So with every new hire, you have burden the reviewer again? Wouldn't it be better to make the default so that Visual Studio burdens the primary developer, instead of the reviewer?
I'm not an idiot, but I don't fully understand git. I am coding for a living, and I use git every day. I probably could sit down for a couple of days and fully understand how git works, but I've never needed it, I understand how basic git operations work, and I stay away from commands that I don't understand. With GitHub desktop you don't need to open the command line for any standard operations, I only need to use the terminal for cherry picking.
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.
I've definitely been the victim of my own git hubris.
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.
That breaks a very simple rule that a VCS tools should adhere consistently. Do not make destructive changes unless explicitly told to. Since most other commands to not allow you to do this without -f, the same should apply here.
I'm not sure I see your point. The entire reason `git push --mirror` exists is to turn the remote end into a mirror of the local end. By definition that's a destructive operation. What would it do without a further --force?
If you just want to push all branches or tags you should use --all or --tags.
Because you normally cannot make remote destructive changes without the --force. Unless you know the commands that does that by default. That is bad UX.
Probably because removing branches from the remote doesn't make the commit history inconsistent with any copies made before the push. That seems to be the only case where git second-guesses what you tell it to do.
mistakes happen.
it is a testament to the power of git that your command didn't cause permanent damage. and yes, it could have been worse.
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)
...and if you didn't know that, you shouldn't be using git!
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.
I get it, but I'm not sure you should fault Git for that. Nothing like that has ever happened to me and I wouldn't use a command I don't know in a critical setting...
Any sane piece of software should warn you before doing a highly destructive operation.
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.
I'm not sure I follow your logic: why not take a few days to learn the fundamentals of git? I did that a few years back (and I'm not saying I read the source code, just learned about the base concepts from a few blogs and played around with some more advanced commands), and it has paid dividends _every single day for the last several years_. For example, I avoid tracking branches and have started using `git fetch`, `git merge --ff-only <remote>/<branch>`, `git reset --hard <remote>/<branch>` and `git push <remote> <branch>` to push and pull remote code. Even these slightly lower level commands will start to help you understand what's going on behind the scenes and take the mystery out of, say, rebase conflicts.
I am limited by time on what I can learn, every day I have five other things I'd rather spend my time learning about instead of git. The "git experts" that I know of are no more productive than me and more often than not do annoying things like rewriting commit histories after I made comments in their PRs, that I'm not convinced it's worth the day or two I need to learn it fully. 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. This is probably akin to trying to understand how your car works when all you need it to do is get you to work. Changing tires is about as much as anyone who's trying to be productive should know about their car. Call a mechanic for anything else.
"The 'git experts' that I know of are no more productive than me and more often than not do annoying things like rewriting commit histories after I made comments in their PRs, that I'm not convinced it's worth the day or two I need to learn it fully."
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."
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...
That's a very shortsighted view on the world. Particularly if you're working with other people.
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.
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.
I've never worked in an environment where it was expected or used. As far as I can tell, no time has been wasted as a result. How would it cause time wasting?
I believe I've really only needed to do that once. git bisect handled it in about 10 minutes IIRC. It's hard for me to imagine how I could achieve a net time savings against that level of commit-hunting.
> I spend a great deal of time looking through history to find bugs.
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.
Your insistence in purposefully not understanding how to use a tool in your toolbox is frankly saddening. It's literally part of your job. You interact with it presumably daily, yet you have no clue how to be effective with that tool. And you say others are annoying for learning how to use their tools.
Cooks and knives are a bad example, because sharpening knives is easy. I am not a cook and sharpen mine too. It takes like 15 minutes to learn how to do it, and a similar time to actually do it.
Most piano players don't have a clue about how to tune their pianos, though.
Oddly enough, pianists not knowing how to tune a piano is an anomaly in the music world, as most other artists know their instruments inside and out. The Times did a piece on this just the other day: https://www.nytimes.com/2020/11/12/arts/music/piano-tuning.h...
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.
> 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.
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.
I would suggest it's far better to understand the data structures inherent in git and how those data structure changes are tracked and merged. Then almost all operations in git become clear.
And as a side bonus it will probably make you a better coder.
Because most options are named after parts of the underlying structure. At least for me that makes them much easier to remember. There are some exceptions, but in general there is a logical system behind the naming.
> I probably could sit down for a couple of days and fully understand how git works
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.
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.
There is a minimum bar for programmers I'd want to work with. Fully understanding git, for me, is part of that bar. The problem is that many programmers don't know how fundamental git is:
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.
> 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.
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™.
With that attitude, I would never, ever, ever, hire you.
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.
> With that attitude, I would never, ever, ever, hire you.
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.
It's not a test of grit. git happens to exemplify -- as well as any system I know -- many aspects of good data engineering. If you're into data and ML, those are things you ought to know too.
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.
Probably the biggest problem with the git interface is that the interface exposed to the user isn't sufficiently abstracted from the implementation.
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).
Then you'd need centralised protections to decide who can delete and you instantly lose the distributed features.
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.
That doesn't matter, the way people actually use git is that almost all repositories have someone or some small group who rule them, so nothing is really lost by having an easy option to purge things from history. And an inconvenient option (possibly more than one!) does exist.
It matters a lot, because the use cases you've seen aren't the only ones that exist. In a tool so widespread as git, that is really not surprising.
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.
Any system will get dragged down by the need to support all sorts of legacy use-cases. I think there's an xkcd cartoon about this?
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.
You mostly lost me at "point-and-click", but I'll bite.
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.
You 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.
Yes but filter-branch is horrendous and could very easily result in unintended side-effects, as well as potentially being very slow. I think this command is a great example of the problem; what a user really wants is an undo button but what git gives them is this thing.
I use an x86 CPU every day for work and I have no idea how it works in detail, and thanks to the magic of separation of concerns I don't have to (perhaps apart from a few specific things like vecorizing instead of loops that I really do need to know about).
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.
It comes down to your distance from a specific 'tool' or system.
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.
> 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.
So do interpreters, compilers, package managers, virtual environments, build systems, CI systems, test frameworks, targets, hosts. Your code doesn't exist in isolation, you need to grok how it works with the codes others have written and will write.
But for each one of these, the less I have to know about its internals, the better.
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.
You want simple internals, and one would expect programmers to understand those internals. You want the userspace to do obvious things with those internals. You don't want magic in between. Understanding internals is a feature, not a bug.
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 take the view that developers shouldn't be spending their time fixing their VCS.
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.
Everyone starts at the ground floor. What would you tell a beginner who has to figure out 20 different technologies including git to get a basic web project going?
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.
I would tell them they don't need to figure out 20 different technologies. If they think they do, they've missed the point of the "basic" in "basic web project". If the 20 different technologies in your example include such basic things as an IDE and version control (evidently it includes at least the latter), I would tell them to start at the basics and learn the tools before they expect to be able to use them.
This is a disgusting, harmful take. You should really step back and rethink your assumptions here. Git is a tool that’s meant to make things easier. It’s complex enough, though, that it’s a stumbling block for a lot of folks for a workflow that really shouldn’t be so complicated.
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.
It's evident that you think requiring basic competence is toxic, but you don't really compel me to feel differently. You have told me what I think is the case is toxic, wrong, disgusting and harmful. I now know you feel strongly about this.
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.
Not the person you're responding to, but I have my own two cents:
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?
You're not the first one to say that it's hard to use right and I agree with that. This is true for a lot of powerful tools. At the end of the day, what is intuitive is what you have used a lot. If you're using a tool that fits an entirely different paradigm from what you are normally used to, it's going to be unintuitive. It's fair to say this frustrates everyone, especially in the beginning.
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.
That’s a similar approach to mine. I tend to learn enough about something to “get the job done.”
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.
I learn similarly (breadth first search + going deeper when needed) and my wife just does depth first seach. I've tried studying with her when we were at university and we just couldn't make it work - she would want to go 10 levels deep into the first subject and I would get insane trying to remember all the nested questions that get us there withotu understanding where the thing I'm learning about will be used :)
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.
`git status` is required to determine which untracked files you need to add. And then, of course, `git add` would be need to be added to the list too. To add untracked files you could use interactive mode `git add -i` and forgo reading `status`. But you can also `git commit -p` if you only modified files and forgo the `add` step.
And to give yourself a sense of the commit graph, these aliases come in handy
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 never worked solo. My teams tend to be around 6-8. Across a dozen teams, myself and nobody on the team save a couple even looked at the graph. One who loved a clean history showed it off, people thought it was pretty, and went back to work as normal. `git commit -am 'slightly helpful message' && git push origin $branch` does about 90%+ of what I've needed. When we merge the branch, squash merge works fine. History graphs, I've never felt the need for them.
Each to their own. I use it in situations where i want to know what other people are basing their branch from. Which, for projects I've worked on, can have real consequences. For instance, it may prompt me to rebase upon their work sooner, or even give them a heads up that theirs some useful change I'm submitting to the trunk.
ah, that is likely part of it. We always branch from master and merge back to master. Builds prevent failing code from merging. It is rare that we branch from a branch, and that 2nd branch would never be merged before the first.
During rapid mobile and frontend development, occasionally I'll be working on someone where there's co-depending feature branches, but for the most part the team usually follow something like git-flow. But I take your point that viewing the graph isn't essential, and those aliases might look scary on a one-page crash course. (I really think `git lol` and `git lola` should be first class citizens of a git installation though)
I think the most common usage of that - switching branches - could be replaced with `git switch` now. That leaves `git checkout` in the set of more advanced operations for more niche use cases.
Same goes I think for `git restore` over `git reset`.
Correct. The use case falls under `git status` really, it will give you boilerplate commands like `git add`, `git reset`, `git checkout -- file`, or even `git rebase --abort` depending on a situation.
So this, to me, is not a 'benefit of git' it articulates in some ways how bad it is (although very powerful).
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.
You can't push a rebased branch without`--force`, and the server can be configured to disallow it entirely. This is exactly how it should be: I want to be able to rebase my by public branches but not the public branch.
" I want to be able to rebase my by public branches but not the public branch."
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.
Stack exchange has multiple answers for most questions. It's not a useful metric; the domain is inherently complex. git has warts, like c++, go, react, npm, rust and all their cousins.
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.
you shouldn't change history once you make it public, how hard is that? that's the golden rule, if you promise something to be immutable, stick to your promise
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".
You should, or do you just merge updated remote branches into your stale local branches? A lot of new developers seem to do that here until we explain to them how it messes up the history.
> do you just merge updated remote branches into your stale local branches?
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.
We don't merge one-off branches into other one-off branches unless they're all under the same feature. Everything goes via develop when they're complete, and new one-off branches are created from develop.
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.
> I'm not an idiot, but I don't fully understand git. I am coding for a living, and I use git every day. I probably could sit down for a couple of days and fully understand how git works, but I've never needed it, I understand how basic git operations work, and I stay away from commands that I don't understand.
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.
Imagine SQL databases worked exactly like they do now under the hood, but instead of current SELECT/UPDATE/INSERT/DELETE they used like 15 different commands with at least 4 switches each.
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.
SQL presents an static picture. It doesn't really provide a way for you to manage and integrate several different views of the world or provide a means to retrieve the history of all changes you have made throughout all of history.
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.
> It doesn't really provide a way for you to manage and integrate several different views of the world or provide a means to retrieve the history of all changes you have made throughout all of history.
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" :)
Perhaps what's needed is an ISO committee to standardise git, or even version control semantics in general, similar to C, and in particular SQL. Once everybody agrees on how it should look, the community can swallow the pain of migration safe in the knowledge that new possibilities are unlocked.
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're still imagining a centralized solution with a single source of truth and less power than Git. Git history is a directed acyclic graph, not a single linear timeline.
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 :)
Agreed - I started to use version control back with SCCS somewhen in the early nineties, and RCS, CVS, Subversion, ClearCase, some Microsoft horror with a name I can't recall, and a few others. My conclusion is exactly the same as yours: "Git is the simplest version control system I've ever used." And it also improved my overview over what happens and has happened in the past - I can jump back in for stuff I haven't touched for many years. So I now think of the older version control systems I used over the years as simple "snapshot backup" systems, not real version control.
(NB: I've never actively used Mercurial, other than because some projects use it, so I'm not comparing Git and Mercurial, or the other one or two systems with similarities.)
That's possibly the one.. I worked for a year on a customer's site, and the source we delivered had to be put into their MS VC every time we delivered it. The major pain was that the namespace was flat.. you couldn't have more than one file in the whole tree called "Makefile" or "ChangeLog", for example.. so we made a transformation tool to make every file name unique before it got pushed into the version control system, and a reverse tool which transformed back when you checked it out, so that one could build the software.
I don't get that either. There have been people here arguing that svn and mercurial were both easier to use than git.
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
Fork is great, I paid for it happily. It's UI makes sense, radiates the right level of information, and you can use the keyboard almost exclusively. Heavily recommended.
The underyling concepts are fine, the problem with git for me is the inconsistent command line interface. Stuff I'm doing less often than once a month I have to check in the manual every time. And it's nothing inherently hard - stuff like removing one change from staging or cleaning up local branch to be exactly like remote. The interface just feels like stuff is arbitrarily assigned to different commands :)
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 don't know why people insist on using the command line for their dvcs.
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.
You don't have to learn 7 IDEs, I've never used git commands in my IDEs. Just use one git client.
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.
I've used a lot of different version control systems over my many years in the industry and git definitely isn't easy. The basics aren't hard but it's easy to get into a pickle if you need to delve slightly out of common patterns.
The git CLI tool isn't great either -- that's probably the hardest part of git.
Quite some years ago we switched from git to Mercurial and the amount of VSC mentoring and unfucking the "VCS guys" had do became almost zero. People seriously just got it. Some argued that is was because they had to learn with git, but... since then we've made the switch back to git for other reasons and we've back at wrangling with the tool again. I'd much much rather use Mercurial with Evolve extension - that is really good.
I’d be inclined to disagree. I found the learning curve to be quite steep. When you’re used to having a centralised VCS hosted for you it can seem a bit of a chore to take on all this extra responsibility. Once you’re on top of it though it’s great I wouldn’t use anything else.
> When you’re used to having a centralised VCS hosted for you
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.
But you are free to use Git in the old centralised way. You don’t have to get into workflows and stuff if you don’t want to. The , just as in the purely centralised case you are still reliant on a oracle but that’s okay in most cases.
I think there are many aspects of Git that are obscure/error-prone regardless of how well you understand its implementation.
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.
Git is I think objectively more complicated any other popular VCS, simply due to the fact it has much more in the design model.
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.
Git is more popular because Github used Git and Github was better than google code or sourceforge. Bitbucket got like 80% of the way there but was always a few steps behind. Had bitbucket taken off rather than github (which is much more to do with the web UI and network effects than the underlying VCS), we'd all be using hg now.
This sort of developer blindness once you have learned something is why we need user interface people as a whole separate discipline.
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).
Git's hard when you see googling for syntax as a failure in the system. If you see getting SO answers as working as designed, it's quite easy. The main learning curve is just the idea of everything being branched, which is an increasingly common concept in many spaces.
I slightly disagree. I think git is simple, but the UX (the way the commands and flags are designed) is really bad so that's why it's perceived as hard.
It's the case with most UNIX CLI tools and if the author's complaints are true, do we then have to change all UNIX CLI tools? Maybe? The reality is we can't and probably don't need to.
"Truly understood" is close to a holy church I guess.
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.
It's years ago, but I recall as a rookie I found mercurial way more approachable and easy to grok. Still distributed and a similar model to git, but considerably more approachable CLI interface and manpages.
It doesn't matter how easy the concept is if the information it contains is not something I can estimate, and in the case of git all the power is coming from indirection, which is famously inestimable stuff.
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.
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.
"You wouldn't expect anyone to operate a table saw"
? 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."
> 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.
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.
Having used a few of these version controls over the years each one has its kind of 'core' strength. Most of them evolved next to each other and borrowed the shorthand of each other and copied each others API/GUI/CLI (mostly), and the shorthand of a physical library. git on the other hand stands alone in its interface. in many source controls 'checkout' for example means I get exclusive control of this file on this branch. Where as in git it does not mean that at all. That is where much of the misunderstanding comes in for git. The commands are kind of the same names but do very different things.
I've always found linear algebra to be far simpler than any other advanced mathematics. It's basically just a lot of book-keeping and consequences from that. Yet I know smart people who failed it multiple times and had to change majors to avoid it. That makes me pause before dismissing people who complain about it.
The article has a better way to assess difficulty, based on how easy it is to teach other how to use it.
Mental model to use SVN for example was quite simplified.
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.
Do you really think the .. and ... notations semantic differences between git-log and git-diff are reasonable?
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.
You could easily write pages about local/remote branches, heads behaviour, etc. in git. Mercurial also gives you an extra option - bookmarks, but you don't have to use them at all.
The deeper explanation doesn't mean more complex system.
The only concept that I can't put into my muscle memory is reverting changes for one file before commit. This is very easy in SVN but for some reason it's not intuitive git (at least for me), why there can't be something like `git revert filename`. Thankfully I have GitKraren that is helping me with things like that.
Yes, it works but not intuitive. I mean why use the checkout for the file reversion? And I think that's the problem of git: it's powerful and it works, but it's really not easy to get started.
It's like shorthand for git checkout <current branch> -- <files>. You're only omitting the current branch which is the default. I'm not sure if it's intuitive but it seems pretty coherent.
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.
There are numerous git <-> svn cheat sheets ... this is literally one of the first things I learned. I’m kind of bewildered by this to be honest ... I don’t know how somebody with a technical qualification could have trouble with this ...
We shouldn't need a cheat sheet. We shouldn't need Linus's brain dump to be able to use a tool. The Git UI directly models the Git internal model and that's just bad design. It's a completely leaky abstraction.
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.
With that attitude, I definitely wouldn't want to work with you either. I also love the assumptions about me and the thinly veiled ad-hominem :-)
We should be able to admit that a tool has a crap UI and cut out the macho geek attitude.
I've been working in this field for about of 15 years and the amount of needless pain we endure from core tools is unimaginable. I'm waaaay past the learning curve for Unix tools, git, etc., but let's not pretend that they're awesome UX wise. They're awful.
We've just learned to endure the pain and we've internalized it.
Flaming other users like this and https://news.ycombinator.com/item?id=25121823 will get you banned on HN. Would you mind reviewing https://news.ycombinator.com/newsguidelines.html and sticking to the rules on HN? We've had to ask you this kind of thing more than once before. I don't want to ban you because you also post good things, but at some point protecting the ecosystem is more important.
Thanks for the :-) makes me feel like we're not having an argument any more.
As an engineer you should also know, that often assumptions are all you've got to go on. The only way to address uncertainty is to get into the details and figure out what's going on. Complaining loudly and fruitlessly about things is good for getting emotional support but it's not generally a good strategy for getting things done.
That's just stupid. We're not talking about "users" here, we're talking about "engineers". If you can't grasp the complexity of Git, you've no business using it. You need to be working in an environment with a centralised VCS and somebody administering it.
Unless you mean just VCS for yourself, in which case you could probably just use anything you liked rather than complaining about it ...
And it's not manliness to say that if you can't grasp complexity you really shouldn't be writing code. That's self evident. It's the whole point of what we do. I'm not looking down on people who can't code - but it's horses for courses. To suggest anything else is just bonkers.
You could have read their comment as saying that they have things they'd rather be doing than learning Git. Instead you took the position that expressing a desire for nice tools is a sign of their total incompetence at programming, that they are complaining because they cannot grasp its complexity (despite them saying "I can use Git" which suggests they can grasp its complexity). You dismissed "The Git UI directly models the Git internal model and that's just bad design", launching straight into calling them stupid and saying they need handholding, for merely wanting good design - because good design makes things easier to use, and things being easier to use is for stupid people.
You could have argued that Git is easy to use and therefore they are stupid for not being able to use it. Or that the interface modelling the internal workings is a good design. Or that Git's complexity is necessary and no simpler interface is possible. Instead you agree that it is complex and thrill about the complexity and use it as a showoff point about how it makes you superior. That's the manliness part. Not as you willfully misrepresent it "if you can't grasp complexity you really shouldn't be writing code" but "if you don't want to spend your life on the complexity of a supporting tool unrelated to the problem you really want to solve you really shouldn't be writing code".
Git is a tool in support of programming, learning Git is not the whole point. Programming involves dealing with complexity (often in the sense of simplifying complexity and hiding it away), but that doesn't mean everything has to be complex to use, and it doesn't mean that someone has to enjoy the complexity in everything to be a good programmer.
Git is hard because it precisely models the complexities of concurrently modifying source code on multiple computers. It explicitly models all of the concepts and operations that are relevant in that domain - branching, merging, my local changes, the server that my local branch is kept in sync with, rewriting local history, rewriting public history. Can you shoot yourself in the foot? Absolutely, because this stuff really is non-trivial. Could it be made easier? Yes, by limiting what operations you're even allowed to make, and streamlining those (c.f. git flow).
> Why can't there be an equivalent of stash that keeps track of which parts were added and which weren't?
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.
> What do you mean by this? It sounds like how stash already works.
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.
> 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).
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."
But FETCH_HEAD only exists because of the fetch command. Git knows what the upstream branch for this branch is. It should know what the remote-tracking branch for that branch is. So why isn't there a command to merge that branch in?
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.
> Why can't there be an equivalent of stash that keeps track of which parts were added and which weren't?
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.
> 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 would be great to have a GUI tool that allows you to do common tasks with a sort of Wizard interface with validation, precise human-understandable explanations, delayed execution (like GParted) and Undo functions. Personally, I don't use GUI tools for Git because they are either as complex as the command line version or I'm afraid they do something under the hood that is not what I intended. I'm not sure GUI tools for Git are programmed in a way that makes data loss impossible.
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.
Exactly what I feel about this tool. I don't get it what is the structure of the inner tree of git changes. Once I though I understand those graphical graphs where branches go out of other branches and than after some commits are merged back. But then I learnt something more and I lost confidence in what I believed before.
Arguments against git being 'too hard' seem to fall into these categories:
* 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.
If you want simple and intuitive interface, then use Source Safe. If you want your team to be performant, then you have to deal with the complexity of parallel work and merges, where git shines.
Ask your manager, which problem is the problem for him.
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.
I see a lot of criticism but not very much any suggestion that would avoid users having to learn how to rebase on an origin master branch or how to force push when they rewrite history. All the git interfaces, including github's web interface particularly, are fine to fix a typo but not really to iterate and create a perfect history of commits.
Based on my experience with users who did not have a programming background, there is no reason for letting them know about neither rebase nor rewriting history. If you are rewriting history, you are already ahead of the curve and you can use the command line. Commit, push, pull, branch and merge are all 90% of users need, and those last two are already an advanced topic.
For a good example of "user friendly git" I suggest taking a look at mercurial.
I cannot live without git, but somehow I still "hate" it.
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.
When I first started using git years ago as a beginner to programming, I always wondered why it didn't just work this way. Since then I've just gotten so used to it that I forgot about my desire for it.
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.
Git is one of those technologies where it's super important to get a good grasp of how to internals work. Once you got that, it get easier to answer git questions for others or yourself, and to read the documentation or man pages, as you know what is happening.
With how software devs use git, it's 100% worth it to read a good book on it.
> Git is one of those technologies where it's super important to get a good grasp of how to internals work.
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.
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?
I agree in the sense that it is important to understand the underlying concepts of Git. Once that is clear in your mind, it becomes much easier to use.
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.
> Git is one of those technologies where it's super important to get a good grasp of how to internals work.
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.
Schoolchildren can write documents. They can't write software with many authors creating disparate, conflicting changes across vast space and time. Complaining that git is too hard is claiming this is easy.
The parts of it that involve Git are easy. By far the most difficult thing is resolving merge conflicts, but Git farms that out to third party software, and nobody here is talking about that.
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.
> Git is one of those technologies where it's super important to get a good grasp of how to internals work.
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 would also love to get some recommendation on git. I'm using the github desktop gui atm (very new to this world), but I'd like to start learning git. it is kinda intimidating.
Use command line. Try creating playground repo and play with it. You can use github's private repos. Use separate accounts to emulate merge conflicts. Start with only those options you feel need: such as tags and so. Read about work models (git flow, and others). Try them in your playground repo.
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!
https://github.com/FredrikNoren/ungit is one of my favorite Git tools. IMHO it is the perfect compliment to the command-line interface since it provides a nice visual model of your commit graph and branches. The graph is interactive so you can use the GUI for things like merging, rebasing, cherry-picking, etc (very nice for visualizing those changes). But at the same time, the Ungit interface mostly just stays out of your way unless you need it. It does not try to force you into a certain workflow or usage pattern.
The directed graph isn't the problem. I think people can deal with the idea that other people have a different version of the code from them. The parts that are hard are the horribly inconsistent commands and the complete mess that is how the staging area interacts with everything else.
The commands suffer from backwards compatibility. And at some point in git's development it was easier to get new options to existing commands approved than new commands. So that's eg the reason 'checkout' and 'reset' do lots of different things.
I wonder whether we could create a much better and more consistent command line interface from scratch?
With most software in general, we usually think the very definition of "easy to use" is "a high portion of users and potential users find it easy to use."
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.
The UX design of git is horrible, granted. To me this article read as "I want a GUI", while having some good points.
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).
Agree. The argument “well this is a hard domain so tools will be complicated” I don’t buy at all.
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.
Git can still solve an incredibly complex problem, have a lot of capability and complexity, etc, and still have lousy porcelain.
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.
It's probably laziness. Is that such a bad thing though? I think its ok to expect tooling to be easy so we can spend our times on actually writing code. To me it's the same thing as expecting auto completion and line by line debugging from our IDEs.
> It's probably laziness. Is that such a bad thing though?
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 =)
The whole point of the article is that not everyone is a [professional] "dev/SWE", or in other words:
> ...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?
> Imagine if git was lost and it had to be recreated, would it make sense to rebuild it exactly as it is now?
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.
You're right, but I think you've taken my hypotethical scenario more literally than it was intended. I was more imagining if we lost git and everything that went with it and were free from the real-life concerns like backward compatibility - an opportunity for a completely fresh start.
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.
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.
It's amazing how this often comes from people that's quite accustomed to spend a considerable amount of time in learning their tools, being it complex math, programming, scientific instrumentation, scientific type-setting. But when it comes to version control they expect it to be able to just use it without any effort. I believe git being hard is just an excuse to not change their current workflow.
As usual, in the discussion there are a lot of folks who's advice/opinion boils down to "rtfm" and "it's not the tool, it's you!"
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".
What I often experience (see also a lot of comments here):
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.
>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.
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:
I've trained multiple teams to use Git (which means I've been their on-call tech support) and I agree the learning curve is tough. However I argue that the value added is so high that the initial curve is worthwhile. I usually start by explaining that Git was made by kernel coders who like low level access, so git hides nothing from you and provides a very generic solution that works for almost everyones use case. GUI tools will cover you in simplest of scenarios, but it's a matter of time until you need to do something marginally complex and are left hanging out to dry. I advise not using them at all because the details they hide are the only thing that will help you understand the advanced features.
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.
As with many things, the solution is complex because the problem is complex. Managing code history in a distributed manner, handling conflicts and allowing cooperative coding is not an easy problem to fix.
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.
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):
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.
Yes I don’t think they can change the default now but many many people operate this way (commit everything not ignored), so most of the time don’t need to separate stage and commit (I agree there needs to be a way to do it, but I use it rarely).
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.
I'd personally also love a config flag (enabled by default, perhaps) that offers more explanation about what the commands actually do as you run them. In other words, "explain like I'm five" logging or "tutorial mode".
I'd say rather 'Version Control is hard'. It should not be that technical.
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 git CLI is too hard. I'm the "git guy" at work and can always fix people's problems and never have to resort to delete and reclone. But I don't use the CLI. I use magit. Using git is just doing operations on the DAG. Git's DAG is the most elegant implementation of a version control system that I've used. But the CLI is awful. It makes no sense. Other Git GUIs make this even worse by adding yet another layer on top of the already bad CLI. What you need is a new porcelain, like magit.
Since my experience with Git is much less (too much solo work, so you don't get exposed to the same scenarios as team developers do), I'm now having to handle new situations in my Git use.
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.
To be fair I have seen a company who had a dedicated git guy who was committing, merging, pushing whatever on behalf of the developer after nth time some of them screwed the repo completely.
When I started learning how to use I had people telling me it is difficult, but were not able to explain why they think it is difficult and I started learning having this in mind and that made it unnecessarily complicated. I think once you know all the terminology and a few workflow scenarios, then it is very easy.
Not Git is which is hard. Distributed systems are hard! So there is a really hard problem to begin with. One specific example from the post to delete a branch. There is no way to simplify that if you want to make a truly distributed system.
> I feel that nobody should need to have spent so much time in a terminal to be able to understand those things.
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.
Centralized still makes sense for some things that should not be collaborated on simultaneously! I have used git when working with electronics and part libraries, but there were occasionally merge conflicts with the files when someone would forget to merge their work in. I wish we would have used SVN for those things!
I think the "just Google the answer" mentality to overcoming Git's obvious shortcomings is really problematic. For example, we once had a junior developer run into a problem with Git and before asking anyone else they went off and found an answer on Stack Overflow that solved a similar but slightly different problem. They naively ran the suggested solution without reading the documentation and wound up deleting our entire remote repo. Fortunately we were able to recover everything...
For context, we used SVN successfully for years before that without ever running into a similar situation.
Git is like piano. You can play chopsticks or Berliotz. Are piano's too hard? Unlike other tools out there, git is utterly transparent on the mechanics above and under the hood. This coming from someone who has gone trough the gauntlet, MS Visual Source Safe, ClearCase, CVS, Subversion, Razor and (gasp) Perforce.
Compositional UIs are extremely hard to learn. You have to be a composer! Quite a high bar, but once you can clear it, you can do things that others consider impossible. Like writing a Symphony Fantastique. Wrapping the composable interface so that the 80% use cases don't require the user to be a composer is the challenge here, and what is interesting is that GitHub seems to be failing so miserably at this according to the folks in this thread.
Git is indeed hard, but it’s also far too easy to screw something up, sometimes irreversibly. Before I became much more
competent with Git, I used to spend far too much time trying to figure out how to undo or fix things. My strategy eventually became “just be extremely careful with everything”. That said, I have learned to judiciously use GUI tools such as those built into IDEs, but I have had to make conscious efforts to understand the commands they’re using underneath.
Let’s also not forget that version control — and any kind of synchronization — in general is hard.
Git should have been a library to create multiple compatible CLI/GUI implementations.
The Git CLI has become too bloated to use. It will take a month to read through the manual and learn all available commands. A well-designed VSC should not take that long to learn.
> The Git CLI has become too bloated to use. It will take a month to read through the manual and learn all available commands. A well-designed VSC should not take that long to learn.
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.
nobody has to read all man pages for all commands. In day2day operations, you maybe use 2 handful of commands, if at all. Everything else can be looked up on demand.
You also don't read all of the documentation of the standard library of your programming language before you start using it.
Git is a beautiful system with an ugly UI. Semi-random English words used that seem to explain a different action than they really do, especially mixed with --arguments that sometimes make a command do something entirely different.
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.
Git is different from TFS/SVN.
I wonder if Bitkeeper and other DCVS solved the user friendliness part.
Not every programmer nowadays is a greybeard, nor do they need to be. If Git can be made easier to use without displeasing greybeards, it should (or: please don't make it into a useless toy).
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.
The whole point of software is to reduce or manage complexity. Git cli fails miserably at this.
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.
Darcs has a great UX. Please to use and still powerful. It inspired some small parts of the Git UX like the `--patch` mode for `git commit`.
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:
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.
I was doing a proof of concept work on transferring a mercurial repo to git, following the official documentation. I then used push --all to copy all the changes to the shiny new bitbucket server (corporate decision, we didn't had the choice...) then wonder why all the tags were missing. Apparently, by default push --all doesn't push the tags...
There is GIT (the system itself) and there is the CLI.
While GIT itself is very elegant and clean, the CLI is the exact opposite. In my experience people who struggle with GIT mostly struggle with its CLI and do a lot better with a graphical interface, given they understand the concept of distributed VCS.
The article is about GitHub writing a new porcelain in Go that matches GitHub's semantics better. And I think that's the key point: the main git porcelain was hacked together by the Linux kernel team to match their workflow.
Now, 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.
So a lot of people at my company were struggling with this too, but I think we found a pretty good solution! We found a tool called ghstack (https://github.com/ezyang/ghstack) that makes it easy to manage dependent PRs. A lot of us are now using it.
Git is a well designed, well thought out sophisticated tool.
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.
Git is hard if you allow it to grow into a monster via neglect. Having a clear, consistent process for branching, reviewing and merging code is virtually 100% of the battle with any vcs.
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 just use gitkraken and have never thought about git again. I often have to help out cli-power users that have hopelessly destroyed their branch and do the equivalent of 12 operations with a few clicks and drag and drops. My job isn't to play with / debug git issues, it's to deliver customer value.
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).
I don't think git is hard at all, it's lightweight and elegant, and quite frankly, extremely logical to understand.. Sure, the syntax can be hard to grasp at first, but that's a reasonable price to pay for brevity tbh.
It's important to distinguish the UX from the internals. I don't know the internals, so they may be elegant and extremely logical, but the UX is terrible.
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"
If you think commandline git is complicated, try to make a symbolic link or an rsync backup from the commandline.
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.
I'm still using Mercurial, and I don't regret that decision. I only regret that everyone else appears to have STOPPED using it, so that I am isolated in my own little world away from community like Github.
I've never understood why so many pro developers around me speak so highly of git. I get that its powerful but why does it seem so convoluted?
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.
Whenever posts like this come up, the amount of controversy they always generate I take as proof of git's difficulty. If git were easy, it wouldn't need to be constantly defended by supporters.
Git is a tool that asks the user to engage from the perspective of the internals of the tool. In order to understand what is happening in git, you need to understand how changes move through the system.
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 briefly looked at Plastic SCM and really liked it (https://www.plasticscm.com/). It's design is much more sensible from the get go, and it has a great UX + UI. If things being Open Source is so important, then I dream about a world where gitlab acquired Plastic SCM and makes it open source!
I hate git with a passion and am very happy with svn. Even my business users can learn and use TortoiseSVN in one session.
This feels similar to the no/low code idea. Saying you want to make it more human and doing so without losing some of the power and crispness of it seems hard if not impossible
From the perspective of a tyro, I find it very difficult to catch on the terminology that git uses. There are simply too many concepts to understand and remember. For example, why is rebase so much more complicated while merging two branches seems fairly straightforward. Even after using it for quite some time, I almost always mess it up. In my opinion, git should abstract a lot of details from a regular user to make it more friendly and easier to learn.
The ability to communicate is a separate skill from the ability to comprehend something.
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."
First of all, I'm sure the author knows more about git than I do, so I don't wanna come across as trying to lecture an expert. But I do feel that his main point misses the mark. It seems to be centered around the idea that a lot of reasonable people are surprised by things git won't let them do (or, more accurately, strongly advices against doing). The problem is that most of these things are only "reasonable" from the point of view of someone who hasn't thoroughly thought through what a DVCS has to do. A lot of the "reasonable" questions are raised from the point of view of "this is a tool for sharing changes to code". But that is just a nice side-effect of what a DVCS aims to do – it is not the goal.
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.
> You have to understand how it is implemented under the covers.
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.
The git plumbing is awesome and robust. The git porcelain (aka the cli UI) is optimized for people that are deeply comfortable with command line tools and setting up aliases for things they do a lot and/or scripting things together. I'm OK with it and I memorized most of the commands and flags I need regularly.
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've never shied away from embracing complexity in trade of more power and/or flexibility wherever it brings me value.
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).
A theme that comes out again and again in the comments here is that in a technical community, complaining that a tool could be better is a reliable signal of a dumb/lazy worker.
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).
You know what's really interesting? I think this is a left/right brain dichotomy here. I learned git on my first software dev job and learned it _deeply_ by executing on the command line. This infused a deep, practical understanding of how the distributed system worked.
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.
That is funny because I read that developers tend to behave as specialists of everything (here raising kids). And that is also sad because looks like a narrow minded point of view
Software engineering basically selects for people being able and willing to sift through vast amounts of information and rapidly build intricate mental models in order to figure out how some system works or ought to be working. That's basically the job description.
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?
I've used and introduced as CTO hg in the past because I think it's easier to understand. less confusing and there are extensions for many (special) use cases. Every org dropped it and I've dropped it more than five years ago because every example on the internet uses git, no one wanted to learn hg and that friction was higher than the benefit of hg to me and orgs.
Git is simply one of the tools you must learn to master as a modern software developer. If you'd say "but source control is simply too hard!" you would probably be asked to leave the building on the first opportunity, and I'd say rightly so. A craftsman that doesn't master his tools is a shoddy worker. I don't see how that is different for software engineers.
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.
> > 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.
While I generally disagree with what he's saying, I do think that most of his points are understandable, even if not persuasive to me.
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.
You could also say that software engineers should be able to focus on building the product, instead of splitting their cognitive capacity between the actual work and fiddling with the versioning system.
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.
I see your point, but in my opinion, part of a job is knowing how to use the tools for the job. New, easier to use or more efficient tools could be created? Absolutely, but knowing how the tools work is never a disadvantage, IMO. And at least we software engineers have an advantage there in that most, if not all, of our tools are themselves software.
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.
But what's the alternative? I dislike Git for its complexity, guns helpfully cocked and pointing at your feet, obscure commands etc. but still feel it's the best of the available tools.
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.
I didn't see a mention of Sublime Merge, by the authors of Sublime Text. It's thoroughly good and free-as-in-nagware to try.
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.
I have often thought about what a truly intuitive, simple, easy, user-friendly VCS would look like. Git is fine for programmers, but what about non-programmers, or student-programmers? Would it be possible to make a VCS that my mother could use without sacrificing too much power?
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’ve tried describing merging and branching to non-programmers a few times. I try not to.
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 can say git is dragging our feet all along. I don't remember subversion being acting this unintuitively.
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.
OK, we got a powerful and flexible version control system which some people find difficult to use. The solution is to build alternative wrappers/frontends (command-line or GUI) on top of it, which present different takes on the best user interface. The author finds local/remote branching confusing? One could build a small `git` command wrapper that will hide it and have more straightforward branching commands. You can think of current git as an assembly language of version control and develop wrappers/compilers for high-level VC languages of various flavors.
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.
Torvalds understands something extremely important about software, and that makes him uniquely suited to make deep, foundational, bedrock software projects.
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.
That's a lot of points for an article that didn't say much. also, I question the author's experience of 10 years if he considered those hard questions to answer.
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.
I think the best thing you can do for yourself as a git user is to learn what things are easily to reverse, what things are hard to reverse and what things are irreversible.
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.
IMHO, No it's not. This isn't Dropbox or FTP. Conceptually, some of thing things Git does is are not easy concepts to distill into a couple commands to achieve what Git sets out to do. Sure, you can use it in a basic way, but that's not the point, Git is incredibly powerful tool.
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.
Exactly! It is too hard for me. I'm webdeveloper mainly full stack since 2009. Since the begining I used SVN but after few years transited to Git. I never had any training where I could put my hands on many use cases and situations of git. I did some tutorials and watched some youtube videos, also checked on f. manual.
I can do pulls and fetches, I don't recognize strict difference (I try this or that). I am able to work smoothly inside my feature branch and can do pull requests to any other branch. I can resolve conflicts. But other stuff is out of my reach - and I now why. Because it almost never happens in day to day job. And if it does not happen I don't remember the procedures to perform.
I have a real question (not trying to start a flame war). Truthfully, why do people think git is hard? Seriously, as programmers we do many, many things that are really hard. Things like thinking about abstract data structures, understanding concurrent processing, etc. I can understand not knowing it and how that frustrates people, but I genuinely don't understand why people are afraid to just dig in and learn git. Some of the commands I admit are confusing at times, and I have to look commands up, but I don't think I've ever looked at git and said, this too difficult for me to understand.
Honestly, I would really love to know, because I have to teach git fundamentals in a couple of months at work.
Git is hard because it has no client. It's a set of primitives for building one.
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.
Meta comment: this thread has over 600 comments after 10 hours (one comment per minute) - most of which are of the form "I use it this way", or "here's a better way to do that" - thus proving the point of the article.
It's not hard nor easy. Git takes time to learn and understand properly, like a lot of things in technology. Sure, it's internally very complicated, but it does a great job at providing a sane interface to use it. I think the problem is really in the approach that a lot of git users think of git in the first place. It's seen as a requirement rather than an aid and solution to a set of very tricky problems. The actual point of VCS in general can't be summed in a sentence. I think the appropriate approach here is to recognize that it will take time to see the value of and learn how/why git does things the way it does.
I don't agree that git is 'too' hard, but I do think the author made a great point how a lot of complexities with git stem from its distributed nature which arose from its origins in the Kernel development community. Most people who use git simply don't work on anything even remotely close to that scale, and will basically only ever be working from a 'source of truth' master/main branch.
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.
Part of the problem with git is that too much of the metadata around a repository (config, heads, remotes, branches, tracking etc) is stored in separate little files somewhere in '.git' This critical state of the repository should itself be version controlled so changes can be examined and rolled back in a clean consistent manor. Git has a reflog so experts can go dig around for the stuff you lost. Imagine if git were more like 'nix'. (that last statement might not help my argument for some of you ;-)
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 some core concepts that need to be grokked to not feel stupid, like commit, rebase, pull, fetch, merge, revert, and more important, when you use them and when you don't.
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.
I think it boils down to Git solving a complex problem in a very elegant way. Other version control systems try to simplify the problem, but the result tend to make some part of a dev team more unhappy than git does
I get frequent questions from other developers (not all junior) on how to fix weird messes in git they've made which is fine if you're just learning but at some point it's like seeing a developer who can't type properly, just kinda why subject yourself to so much extra work to avoid learning to use something. Yeah it's kinda hard and not very exciting but it's powerful, a part of pretty much every software related dicipline and we don't have an easier modern alternative right now. I don't get the stubborness around it.
But this is not stubbornness at all. There are way better alternatives like mercurial but you have to fight with the pious Git believers because they just don't give a flying...
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.
I find it a little confusing, especially when trying to do something a little unusual.
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.
There is a technical difference between an local repo and a remote repo (bare repository) - although I think you can clone from a repo and make this "authoritative", what you usually do is (in your client, not the server)
- 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.
There is a relatively easy way to accomplish this by editing your .git/config file to point at the new "authoritative" repo.
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.
All those commands do is change the .git/config file. Such commands are great for scripting, but really don't need to be learned if you're comfortable editing simple config files with your preferred editor.
Can't remember the times I've had to google "Pop commit and move to another branch", for when I accidentally commit to `master` when I meant to commit it to `feature-branch`...
I agree that Git is hard, but with the right explanation and a good graphical GUI like SourceTree, I've gotten non-technical team members up to speed on it!
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...
I still mourn the loss of Bazaar, Canonical's early distributed VCS.
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.
Earlier this year, I wrote a blog titled 'A simple Git workflow' https://www.iwriteiam.nl/D2009.html#30 and now that I am rereading it, it does not feel simple at all for a first time user. And note, this simple workflow does not even use branches. It was only recently that I found the two global settings that makes lives for first time users so much easier. Why not make them default?
"There is still a chance that between since the last git pull command someone has pushed a new commit. In that case a merge will occur in your history." If you want to prevent these merge commits (I do, I think they're really ugly), you can add git config --global pull.ff = only
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.
Yes I agree there are issues with git, and this may be a great solution!
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.
I've read this as a rant about why we should want a fancier SVN. Unsurprising coming from someone working at Github, but hardly representative of what git was made for and can actually do.
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.
It's even worse. Fancier or not, centralized systems are actually bad for usability in a very important way: Users will always manage to break their local checkout or clone somehow. With git (and many other, but not all) decentralized systems, just using a plain filesystem copy as a fallback or backup, the user is easily able to recover. There are better ways, but this is an obvious one that works without the need for extensive tools, training or docs. With centralized systems, or even GitHub, the user is bound to commit/push(--force)/sync at some point, breaking the central instance, which is much harder to recover from.
I completely agree that git is hard to learn. I had used both cvs and svn before moving to git, and it took me a looong time to really get git. And it wasn't a case of command line vs GUI - I prefer the command line.
The main problem I run into with git is communicating with my teams about editing history and how they shouldn't.
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!
Git is the single-most reliable tool that makes the most sense to me and gets out of my way 100% of the time. Knowing how it works is imperative to using it effectively - you wouldn't drive a car if you didn't know how to use the steering wheel or pedals, would you?
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.
> "I will get you to think about a directed graph or as operations on a directed graph". No human thinks about that!
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.
Git the ideology is great. Git the tool and UI are good for power users, but are abysmal for beginners and non-technical folk.
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.
I've been programming since long before GUIs existed, and Git baffles me. We use Subversion, it's a lot simpler and does the trick.
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.
Git also sucks when someone in your team drags their feet and doesn't use it properly. And when your team is mostly made of non pure comp. science background who have learnt SQL on the job, trying to get them to stick to git is really difficult. There almost needs to be something in between that satisfies this kind of intermediate technical ability and interest.
I think Atlassian could come up with something suitable.
Not sure why you think using git has anything to do with having studied computer science at university or learning SQL on the job.
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.
Well if you want to know how to unpush, here's how. You can also use this to just uncommit locally if you made a mistake, too.
>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.
I use vscode with Git Graph. It gives me a clear understanding of everything, allows me to manage branches easily, gives me access to every command I need, and even allows a great diff view between any commits.
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.
It's about time we should get off of git to something new by creating a bridge like "git svn" for easier migration that's targeted at more general audiences than hackers of the hackers only.
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.
People often blame git for being hard, but did they actually learn git at some point, or do they just monkey-type commands hoping for it to make sense?
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.
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.
I would say that people only need to initially learn: checkout, add, commit, push and pull. Those operations cover most of a devs daily workflow (for most companies I've worked at at least). Anything else can be figured out/taught as needed, it's much easier to learn a new concept when you have a use case specific to you.
I know git internals. But I still struggle to have a correct mental model of developping features on branches that you then merge into a very distant branch.
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.
I see many comments saying that Git is still the best SCM system, which I agree with. Git can simultaneously be bad, and better than any other option available. To me Git has always seemed a little bit awkward. It works well when it works well. I think it it solving a hard problem. I don't think Git is the final solution though.
I disagree. Git definitely has a learning curve just like all tools do. But as an engineer, you should learn it accordingly.
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 use a straightforward workflow, protecting master with PR, with some alias to create a new branch, pull and push, pick, and log.
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.
I agree that git is awful for beginners and casual users but the warts become insignificant after you get accustomed to git. I honestly prefer an industry wide solution where everyone is aware of the warts than having 100 different solutions where each tool has different warts.
The analogy with (La)TeX is strong. That's also very powerful, written by a luminary at the bottom level (Knuth as opposed to Torvalds), and with a command line user experience loathed by most. GitHub etc. are supposed to be like Overleaf. Why aren't they?
I'm an academic. I use git for some projects. I would love something between git and Dropbox: Dropbox's ease of use and automation, but git's ability to add branches. I've struggled to persuade co-authors to use git. There is too much to learn.
Yeah, I learned git because my supervisor was using it on a research project. I made a few mistakes but he helped me mop them up and correct them. Now I use it for everything - I honestly dont see how I could go back. I cringe now everytime I see someone with multiple copies of a file with version numbers on it. I too have tried educating colleagues on it but it doesn't stick unless you really need to use it + intertia of having an established working method.
I completely disagree. There is the very serious danger of replacing an elastic, very simple to learn system which is battle tested in real battles (like kernel development) with a fancy GUI or CLI that can only deal with 10% of the problems I can solve with Git.
I agree with this statement; I am, however, not a Git pro. I have mostly used SVN and am very comfortable with it. Whenever I jump on a project that uses Git, I have to ask a million questions about how to do things. I am just having trouble groking Git.
How to use git is difficult to teach to people who are not familiar with version control. I think sometimes this community forgets that version control is not common knowledge outside of the tech sphere.
A graphical client like Sublime Merge makes it easier, but not easy.
I don't mind hard, if it can justify itself. But after having struggled with git for years now, I still can't find a single thing that it does better than Subversion did, only with a lot more seemingly superfluous steps to do it.
I have to disagree. Got is as hard and complicated as you want it to be.
For the most common usage (commit, push, pull, checkout) it's very, very simple and easy to grasp.
This is like saying "computers are too hard".
An example issue: the interactive `--patch` mode, by far the most powerful paradigm for interacting with diffs, is available for `git stash [push]` but not for `git stash pop`. The CLI is full of inconsistencies of this kind.
> "Oh, I just pushed a change. I really didn’t wanna push that, so how do I undo it?" - adding a revert commit, rebasing and squashing it together with the original is the standard way. I know, it may be painful, but back in the time when I used SVN that was only possible by asking the local sysadmin to run a bunch of hacks on the server.
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).
All of those questions in this blog post comes from people who don’t even look into documentation or try to find answers (e.g. learning), and someone is even hiring them.
As a user who knows absolutely zero Git, I often fumble around for a good 20 minutes at times trying to figure out how to just install someone's project for consumer use.
Git is hard if you don't take the time to learn/teach it.
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.
But that's my definition to hard, there was a thread recently about anyone being able to improve their chess skills by taking it seriously and learning- it doesn't mean that chess is not hard.
> and there’s really good man page documentation now
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.
init, clone, add, commit, push, fetch, reset, checkout, status, diff, rebase and cherry-pick are all you need pretty much. I never use merge or pull. Interactive rebase is the most useful git command.
To answer your question about deleting a remote branch: branches are usually features, e.g. fixes, new features, etc. Once I've pushed to the remote and merged, the branch is no longer necessary. This is why someone would delete a remote branch.
The article's point isn't that there's no reason to delete a remote branch, but that the concept of them is a conceptual leap that one doesn't naturally make until confronted with certain situations.
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.
Git is indeed hard and it would help to have some metaphors for it. One I ofter use (I work in biology) is that it is like a lab journal. A lab journal also needs to be in a specific format, dated, indexed, checked every now and then (by someone else), changes have to be dated and signed.. And it's also hard :)
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.
I work with people who continue to struggle with it, and occasionally make a mess that I have to clean up. They've watched the tinker toy video, and others.
> 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]
> 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.
The actions for the commands ‘commit’ and ‘push’ were always confusing to me.
‘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.
Single commands do many different things, options are inconsistent, e.g. -n does one thing for one command, and a different thing for others, lots of common tasks require complex sequences of commands, etc.
It's pretty telling that there have been multiple attempts to write a saner CLI for Git.
Complaining is not the best strategy for marketing anything. If one cannot use it, why bothering onesepf with more complex problems comes up in software engineering?
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.
Git is not hard - the “questions” in the article are incomplete or not properly framed, that’s why they don’t have a straightforward answer. If you can’t be bothered to understand a crucial tool you use everyday I don’t know how you expect to be a professional developer. Hell even hobbyists have mastered git and are not running around complaining.
“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.
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.