[0] https://beej.us/guide/bgnet/ [1] https://beej.us/guide/bggit/
[0] https://beej.us/guide/bgnet/ [1] https://beej.us/guide/bggit/
I am aware that beej's guides are typically quite comprehensive, but the vast nuances of git truly eluded me until this.
I guess Jujitsu would wind up being a much slimmer guide, or at least one that would be discoverable largely by humans?
As a cloud security analyst that is thinking of going back to coding or DevSecOps, if I'm honest with myself, there is nothing new here that I have not seen before... (This is not a criticism or anything. If anything the problem is myself: if I can allocate time to learn this or use Anki to retain this).
It's also this sort of work that's becoming less necessary with AI, for better or worse. This appears to be a crazy good guide, but I bet asking e.g. Claude to teach you about git (specific concepts or generate the whole guide outline and go wide on it) would be at least as good.
I also think if you are at the “don’t know what you don’t know” point of learning a topic it’s very hard to direct an AI to generate comprehensive learning material.
I have found that asking AI "You are an expert teacher in X. I'd like to learn about X, where should I start?" is actually wildly effective.
I remember fumbling around for ages when I first started coding trying to work out how to save data from my programs. Obviously I wanted a file but 13 year old me took a surprisingly long time to work that out.
Almost impossible to imagine with AI on hand but we will see more slop-merchants.
Branching, making commits, and creating pull requests come easy, but beyond that, I know utterly nothing about it.
The main advantage of LLMs is that you can ask specific questions about things that confuse you, which makes iterating to a correct mental model much faster. It's like having your own personal tutor at your beck and call. Good guidebooks attempt to do this statically... anticipate questions and confusions at the right points, and it's a great skill to do this well. But it's still not the same as full interactivity.
I've never found that I need to touch most of it in the 15 or so years I've been using it, but it's there if your project needs it.
The universe doesn't owe you an easy 10 minute video solution to everything, it's an annoying educational expectation that people seem to have developed. Some things are just that difficult and you have to learn them regardless.
When it’s just a book. I find myself having questions like you mentioned. When it’s just LLMs I feel like I don’t have any structure for my mind to hold on to.
I also feel like there is an art to picking the right order to approach learning a topic, which authors are better at than LLMs.
I strongly suggest reading Pro Git, the official Git book by Scott Chacon and Ben Straub, available for free here: https://git-scm.com/book/en/v2.
I find it very pleasant to read and it really changed my perspective not only about Git but about how to write code in general. You don't need to read it entirely, but suggest at least these sections:
- 1.3 Getting Started - What is Git?: explains a little about snapshots and the three states
- 10.1 ~ 10.3 Plumbing and Porcelain, Git Objects and Git References: this explains Git in its lowest level, which is surprisingly simple but powerful. Those sections were enough for me to write my own "Git" (you can see it here: https://github.com/lucasoshiro/oshit)
How will LLMs be trained if no humans are making learning materials?
We have a basic Git cookbook we share with any new joinees so that they start committing code, but most of them just follow it religiously and don't understand what's going on (unsurprisingly).
However, literally everyone who attends the course comes out with a reasonable working understanding of Git so that they know what's actually happening.
That does NOT mean that they know all the commands well, but those can be trivially Googled. As long as your mental model is right, the commands are not a big deal. And yet, the vast majority of the discussion on HN on every single Git post is about the command line.
Funnily enough the class sounds a lot like the alt text of https://xkcd.com/1597/ (Just think of branches as...), the difference is that that is unironically the right way to teach Git to a technical audience, and they will come out with a fundamental understanding of it that they will never forget.
I honestly think it's such a high ROI time investment that it's silly to not do it.
This is precisely why it enrages me when all HN discussion about Git devolves to the same stuff about how it's complex and this and that.
A technical person who has general sense about basic data structures (Leetcode nonsense not needed) can be taught Git in under 2 hours and they will retain this knowledge forever.
If you can't invest that little time to learning a tool you will use everyday and instead will spend hours Googling and blindly copy-pasting Git commands, that's on you, not on Git.
Altho maybe I'm stretching the analogy too far.
Jujutsu VCS: Introduction and patterns
Git porcelain stuff's plenty good for probably 95% of users. `rebase -i` comes with a guide on which commands do what, and you could write a couple of paragraphs about how to format `git log`'s output with your own preferences and tradeoffs -- and porcelain usually includes stuff as eclectic as `git gc`, `git fsck`, and `git rev-parse` by most accounts.
Git plumbing's definitely a bit more obscure, and does a bunch of stuff on its own that you can't always easily do with porcelain commands because they're optimized for the common use cases.
TL;DR: while Git's big (huge even), a lot of what it provides is way off the beaten path for most devs.
And on that note, I feel like the guide covers maybe 10% of Git :), but hopefully 90% of common usage.
I can teach someone who has never even heard of source control how to use Perforce in about 10 minutes. They will never shoot themselves in the foot and they will never lose work. There are certainly more advanced techniques that require additional training. But the basics are very easy.
Git makes even basic things difficult. And allows even experts to shoot their face off with a rocket launcher.
Git sucks. The best tool doesn't always win. If MercurialHub had been founded instead of GitHub we'd all be used a different tool. Alas.
Appreciate the work! Neat to see you still writing pieces like this all these years later!
A good book by an expert is still better than LLMs at providing high-level priorities, a roadmap for new territory, and an introduction to the way practitioners think about their subject (though for many subjects LLMs are pretty good at this too). But the LLMs boost a book's effectiveness by being your individualized tutor.
(I didn't read the IPC guide.)
Commits are snapshots of a tree. They have a list of ancestors (usually, but not always, just one). Tags are named pointers to a commit that don't change. Branches are named pointers to a commit that do change. The index is a tiny proto-commit still in progress that you "add" to before committing.
There. That's git. Want to know more? Don't read the guide, just google "how to I switch to a specific git commit without affecting my tree?", or "how do I commit only some of my changed files?", or "how to I copy this commit from another place into my current tree?".
The base abstractions are minimalist and easy. The things you want to do with them are elaborate and complicated. Learn the former, google the latter. Don't read guides.
If you didn't, then you won't be included the training set (obviously) and the AI would not easily know about you. Sort of how if you start a really cool company but don't make a website Google doesn't know about you and can't return you in their search results. It's valuable for Google (AI) to know about you, so it's valuable to build the sites (docs) to get indexed (trained on).
Thanks!
I’ve been using Git for years, but I bet that I’ll learn something from this.
Because the C and PL/SQL people are on CVS, I can fix this with vi on the ,v archive.
First on TFS repositories, and now with git grep I can easily find exposed passwords for many things. But it's just SQL Server!
We will never be able to use git responsibly, so I will peruse this guide with academic interest.
Don't even get me started on secrecy management.
I am looking forward to retirement!
tldr: even if you never plan to use anything advanced, you’ll end up in some weird situation where you need to do something even if you’re in the “95% of the users”
no shade, yes ofc you “could this, could that” to make things work and we have been stuck with this for so long that an alternative doesn’t even seem plausible
I didn't even know git switch existed, let alone git checkout was considered the old alternative. I feel old.
To be fair I started learning git a little less than 10 years ago but woah, I can't express how it feels that someone learning git today will be confused of why I use git checkout. Like using old fashioned language.
More on topic, this guide would've been super useful when I was learning. It is really easy to follow and covers common FAQs.
I fondly remember being intimidated by my first merge conflict, aborting it and just doing some workarounds to prevent the conflict.
I am an Old and we never were taught anything about coding with other people who were also working on the same project. I have had many successful projects but never with another person.
With that as a background, does your guide cover things like:
1) Merging. I was told that merging happens "automagically" and I cannot, for the life of me, understand how a computer program manages to just ... blend two functions or whatever and it "works." Does your guide make sense of this?
2) Apparently there are holy wars (see also vi versus emacs) about the One True Way to ... decide on branches and whatnot. Are there pros and cons laid out anywhere?
3) Everything seems broken down into teensy tiny functions when I look at someone's git repository, just skillions of files all over the place. Is this a git thing, a code repository thing, or simply that, in order for multiple people to work on the same project, everything must be atomized and then reassembled later? What's your opinion?
Learning git like this is honestly just hampering yourself
Here's, respectively, a discussion from 2021, and a discussion from a few weeks ago. In the latter, it's brought up that `git switch` is still considered experimental by the docs:
Anyway, the comment I really wanted to make was that I tried git lfs for the first time. I downloaded 44TB (https://huggingface.co/datasets/HuggingFaceFW/fineweb/tree/m...) over 3-4 days which was pretty impressive until I noticed that it seems to double disk space (90TB total). I did a little reading just to confirm it, and even learned a new term "git smudge". double disk space isn't an issue, except when you're using git to download terabytes.
The evidence that the git UI is awful is _overwhelming_. Yes, yes, I’m sure the people that defend it are very very very very smart, and don’t own a TV, and only listen to albums of Halloween sounds from the 1950s and are happy to type the word “shrug“ and go on to tell us how they’ve always found git transparent and easy. The fact is that brilliant people struggle with git every single day, and would almost certainly be better served by something that makes more sense.
1. Create a branch from the intended destination.
2. Merge/rebase/whatever complex operation you need to do into that branch.
3. If successful merge this branch (fast forward merge) into the intended destination.
4. If unsuccessful delete the branch and start over at step 1.
1. it’s possible to get into a bad state 2. it’s not clear what exactly that state is 3. it’s not clear how you got into that state 4. it’s not clear how to get out of it
I understand Git reasonably well. I know a good bit how it works under the hood. When I have a gitastrophe I rarely understand what I did wrong and how to avoid it in the future.
Here’s a recent post from a friend:
“ 0) clicked fetch all to make sure I had latest everything 1) right clicked on master and selected "merge master into branch" 2) made sure there were no merge errors 3) get on the master branch 4) clicked pull again because sometimes switching to branches doesn't work without it 5) right clicked on my branch and selected "merge branch into master" 6) clicked check in and push buttons
About an hour later, someone noticed that everyone's work from the past week was gone. I mean the checkins were still there in the graph, but all their code was basically gone in latest. And because my branch had many commits in it, apparently no one could just revert my merge and it took someone an hour to work out how to fix everything during which no one could touch git”
Somewhere along the way he didn’t do what he thought he did. No one could figure out what he actually did wrong. No lessons were learned from this Gitastrophe.
Does the course material (and perhaps any recordings) have any proprietary information or constraints to prevent you from sharing it publicly? Is this based on something that’s publicly available yet concise enough to fit within two hours? If yes, please share (perhaps in this thread and as a post submission on HN).
I’m asking because I believe that there can never be enough variety of training materials that handle a topic with different assumptions, analogies, focus, etc.
Without knowing for sure what was going on and whether your friend was describing it using the right verbs, I'm thinking (0) didn't pull in the changes ("fetch" instead of "pull") so (1) didn't merge in any new commits, but (4) did advance master, causing it to diverge from what was on the server. Then (6) probably decided to be helpful and did a force-push instead of a regular push so it wouldn't fail on the user. That would cause the server to have your friend's changes, but be missing anything that had been pushed to master after they started working on their branch.
Like others in these comments, I can use it just fine right up until I can’t. Then it’s back to the mini, many, many posts and questions and tutorials, sprawled across the Internet to try and solve whatever the issue is. JJ has shown that a better chrome can be put over the underlying model, And it’s frustrating to me that we are all collectively, apparently, expected to put up with a tool that generates so much confusion seemingly regardless of brilliance or expertise
Listen, I'm not that smart, and I managed to figure out how to solve even gnarly git issues one summer during an internship... 11 years ago? Ish? Now, I know git well, and not just "the three commands". I would be, honestly, so ashamed if it were a decade on and I still hadn't committed to learning this fundamental tool.
Version control is a hard problem, fundamentally, and a tool for experts will always take more effort to understand. I mean, aren't we supposed to be the software experts? If people can't learn git, I wouldn't trust them with the even harder parts of software development.
But this is a common attitude in industry now, unfortunately: a petulant demand for things to be easier, and for someone else to do the learning. Is it any wonder software today is so bad?
You need to think about what you're actually trying to accomplish, and that requires having a mental model of how the tool works. And no, I don't mean under the hood, I mean stuff like "what does a rebase do?" and "how do branches work?"
The Git Book is a great resource for this. I recommend reading it and trying the examples over and over until they stick. I promise, git is not inscrutable.
It did take maybe a year or so to develop the mental model of the how commands map to the underlying structure of commits, and another few years to avoid footguns (like always "push --force-with-lease").
So I think it is probably too complicated and would be happy to switch to a better alternative if one comes up, but what seems really implausible to me is going back to the bad old days of SVN.
Like so much of the porcelain is those kinds of tricks, and make otherwise tedious work much simpler.
Imagine if you didn't have interactive rebases! You could trudge through the work that is done in interactive rebases by hand, but there's stuff to help you with that specific workflow, because it is both complicated yet common.
I think jujutsu is a great layer over git precisely because you end up with much simpler answers to "how do I change up the commit graph", though.... the extra complication of splitting up changes from commits ends up making other stuff simpler IMO. But I still really appreciate git.
On one hand you have the ideal world scenario when each and every change is granular and you can annotate and blame every single line of code with description. On the other hand you have a real world where teams are encouraged to squash changes so that every commit corresponds to a business requirement and you have to engage a whole cabal to smuggle a refactor.
A long time ago I've implemented a routine to use both SVN and GIT, so that I could use GIT on file save, and SVN on feature release. I think it was inspired by Eclipse workflow. Definitely not something I would recommend these days.
I find it hard to judge when things are in a good enough state to commit and especially good enough to have a title.
I might start writing a new function, decide that I want it to be a class only to give up the class and wanting to return to my almost complete function. Snapshot works pretty well for that, but got isn’t really centered around snapshots and doing good snapshots is not straightforward, at least to me.
What do you guys do?
Keep on fighting the good fight, Beej.
Stop worrying about titles and content and commit to your heart’s content.
When ready, restructure those snapshots into a coherent story you want to tell others by squashing commits and giving the remaining ones proper titles and commit messages. I use interactive rebase for that, but there are probably other ways too.
Work in a feature branch. Commit often. Squash away the junk commits at the end.
> ...and especially good enough to have a title.
Who needs a title? It's perfectly fine to rapid-fire commits with no comment, to create quick save points as you work. Bind to a key in your editor.
I treat commits in a private branch the same as the undo log of the text editor. No one cares about the undo log of your editor as they never see it. The same should be true of your private feature branch commits. They are squashed away never to be seen by human eyes again.
Commits are sets of files. They form a tree. A branch is a named location in this tree. The index aka staging area is a pre-commit that has no message. Workdir is just workdir, it doesn’t go in the repo unless you stage it. HEAD is whereafter commit will put new changes.
Do I understand git? Seems like yes. Let’s run a quiz then! Q? A.
How to make a branch? Git branch -a? Git checkout -b --new? Idk.
How to switch to a branch? Git switch <name>, but not sure what happens to a non-clean workdir. Better make a copy, probably. Also make sure the branch was fetched, or you may create a local branch with the same name.
How to revert a file in a workdir to HEAD? Oh, I know that, git restore <path>! Earlier it was something git reset -hard, but dangerous wrt workdir if you miss a filename, so you just download it from git{hub,lab} and replace it in a workdir.
How to revert a file to what was staged? No idea.
How to return to a few commits back? Hmmm… git checkout <hash>, but then HEAD gets detached, I guess. So you can’t just commit further, you have to… idfk, honestly. Probably move main branch “pointer” to there, no idea how.
If you have b:main with some file and b:br1 with it, and b:br2 with it, and git doesn’t store patches, only files, then when you change b:main/file, then change and merge+resolve b:br1/file, then merge that into b:br2 to make it up-to-date, will these changes, when merged back to already changed b:main become conflicted? Iow, where does git keep track of 3-way diff base for back-and-forth reactualization merges? How does rebase know that? Does it? I have no idea. Better make a copy and /usr/bin/diff [—ignore-pattern] the trees afterwards to make sure the changes were correct.
As demonstrated, knowing the base abstractions doesn’t make you know how to do things in git.
I don’t even disagree, just wanted to say fuck git, I guess. Read guides or not, google or reason, you’re screwed either way.
Probably you've been using it for ten years or more at this point and have internalized it, but when it came out git felt way more confusing than other VCSs.
Compare git diff with hg diff for example.
I've also written a guide, targeting devs with basic Git experience. It is much shorter, maybe you or your team can benefit from it [1]
[1] https://www.augmentedmind.de/2024/04/07/ultimate-git-guide-f...
This idea breaks under pressure. People have limited concentration and the more you demand for daily routine, the less there’s left for the actual job. This argument only makes sense in a relaxed setting with lots of time and coffee breaks. But all these problems tend to happen at friday evening when you’re expected to get your kids in an hour or something and this damn repo got broken again.
Yes, things should be easier. Cause you get what you get. If you want people who have no issues with git, feel free to enjoy the greatly reduced hiring pool and stop whining about someone not being able to juggle fifty things at once in their mind - focus on your hiring process and where to get the budget for inflated compensation instead.
Is it any wonder software today is so bad?
I remember delphi and vb time, when people - who were unable to understand or use CVS and SVN - made full-blown apps for real sectors, and it worked. Because it was easy. Nowadays all we have is important dudes with pseudo-deep knowledge of git, css, framework-of-the-month and a collection of playbooks, who cannot make a db-enabled hello username message box in less than a day. I don’t think you’re moving in the right direction at all with this. This paradigm is going further and further from good software, actually.
2) I try to stay out of holy wars. Use the right tool for the job, I say, and sometimes that could even be Emacs. ;) I do talk about a few of the more common options for branching in teams (mostly focused on the small teams we tend to have here in university). And I talk about their pros and cons. But I stop short of declaring one the winner since the best option depends on the circumstances. IMHO.
3) I've seen repos with big functions and small functions, so I don't think it's a Git thing. Students tend to write functions that do too much and are too large, but it's certainly possible to break things down into pieces that are prohibitively tiny. Overall this seems more of a software engineering design choice than anything Git-related.
The worst part about Git is the bad defaults. Seconded only by mismanaged storage. Or maybe being designed for the use-case most of its users will never have. Or maybe horrible authentication mechanism. Or maybe the lack of bug-tracker or any sensible feedback from its developers.
None of this can be helped by the GUI. In fact, beside Magit, any sort of front-end to Git I've seen is hands down awful and teaches to do the wrong thing, and is usually very difficult to use efficiently, and mystifies how things actually work. But, even with Magit, I'd still advise to get familiar with CLI and configuration files prior to using it: it would make it easier to understand what operations is it trying to improve.
At least, this is what it looks like from your own description. This is, probably, what most people do with it most of the time. And the weird corners will be found when they need to automate things, or when they want to deal with modular repositories, or history rewrites. These aren't everyday tasks / not for everyone on the team, but, these things do happen, especially in smaller teams, where there's no dedicated infra person or group these can be delegated to.
Most Git users will never have more than one remote per project, and so will only have a single product built from their source code. Probably wouldn't even know how to configure their mua to send text-only emails, in case that option is even available to them, and would struggle with basic Unix utilities like Vim and diff.
I don't know why Git won the VCS contest. But, I'm afraid, as with many such wins, there wasn't a clear rational reason why it should have won. It didn't make some of the obvious bad decisions which would disqualify it, but so did a few others. My take on this is that communication tools naturally gravitate towards monopoly, so, if one starts to win even slightly, the win will become a landslide win.
Here's a simple example of how people shoot themselves in the foot with Perforce all the time: it makes files you edit read-only, and then you run with your pants on fire trying to figure out how to save your changes, because the system won't let you do that. And then you do something dumb, like copy the contents of the file you aren't able to save someplace else, and then try to incorporate those changes back once you've dealt with the file that Perforce wouldn't save. And then end up with a merge conflict just working with your one single change that you are trying to add to your branch.
I never regretted never having to touch Perforce ever again. Just no.
Try to come up with something simpler than git, and you’ll end up with something like SVN or CVS that struggled with more than a couple of people working on the same files.
Try to make something that is more content aware, and you’ll find out how git got its name in the first place.
It was a disaster. Literally the most important thing for any VCS tool is to never ever delete file I don't want deleted. No more Jujutsu for me.
Someday someone will invent a VCS tool that doesn't suck. Today is not that day.
I'm delighted to see that you're still active and still producing guides. Well done!
A priori, I would have assumed this was one of those "just understand how every layer and every part of Linux works, and using Linux is easy" type arguments people used to make in the 90s - i.e. theoretically true, practically infeasible for most people.
Thankfully, I was lucky enough to come across a video explaining (some of) the git internal model early on, and it really doesn't take that much or that deep a knowledge of the internals for it to make a big difference. I'd say I know maybe 5% of how git works, and that already gave me a much better understanding of what the commands do and how to use them.
Git is designed for the case where you have multiple remotes with no central authority. Except that’s not how any project I’ve _ever_ worked on functions in reality. It makes sense for some applications, but if I say that I run Linux, there’s an assumption that I’m running something compiled from https://github.com/torvalds/linux - I.e. there is a central space.
I’ve used git and perforce in anger for a decade, in teams of 1 to 150+ (with a brief blip in the middle where I tried plasticscm which was a mistake), and I’ve been the “git guy” on teams during that time. If git’s defaults were tweaked for “one origin, probably authoritative” and it had better authentication support out of the box it would be a significantly better experience for 99% of people. Those 1% of people who are left over are going to customise their config anyway, so make them add the distributed-defaults=true flag and the rest of us can get on with our work.
I do deal with multiple remotes quite often and haven't encountered issues. You're right about submodules, I avoid setting up projects with them, even at the expense of more manual work or complicated automation.
I'm definitely not using it as a substitute for rsync - I do prefer to put rules in place to avoid editing (shared) history, for obvious reasons.
Because GitHub offered free git hosting, and heroku came along and offered free hosting that was pretty much point and go.
Combined, you all of a sudden went from needing a sysadmin and two servers (this was pre containers), and the sysadmjn skills to operate SVN and your web app, to “it’s now free and it auto deploys when I commit”.
You shouldn’t ever need to go to the reflog unless you’re in an exceptional case, and fit makes it very very easy to get into that exceptional case.
How do I undo a change and get it to other people on the team?
- follow up, What happens if someone has made an unrelaydx change since?
- someone has committed an enormous change and I want the commit immediately after it but the enormous change doesn’t affect me. How do I get that single file without needing the mega change.
- someone has committed a mega change and pushed it to main, and it’s busted. How do I put my perfectly functioning feature in while i wait for the west coast to wake up and fix it?
I don’t need an explanation on how to solve these issues, I am perfectly able to. But these are daily workflow issues that hit requires you to use external tools, and change entire development processes to work around. And trying to skirt them is a guaranteed one way ticket to a busted workspace
I mean I haven't even talked about how Git can't handle large files. And no Git LFS doesn't count. And Git doesn't even pretend to have a solution to file locking.
I'm not saying Perforce is perfect. There's numerous things Git does better. But Perforce is exceedingly simple to teach someone. And it doesn't require a 193 page guide. I can teach artists and designers how to use Perforce and not lose their work. A senior engineer who is a Git expert can still shoot themselves in the foot and get into really nasty situations they may or may not be able to get out of.
There's a reason that like 105% of AAA game dev uses Perforce.
So, is it possible to deal with Perforce marking files read-only? -- Yes. And it's not complicated, but the whole idea that that how the system should work is stupid. The problem is, however, exceptionally common. In my days working with Perforce there hadn't been a day when this problem didn't rear its ugly head.
So, maybe Perforce is scoring better on some metric, but in the day-to-day it generates so much hatred towards itself that I don't care if it can handle big files better than Git does. I only need to handle big files maybe a few times a year. And I prefer to get frustrated only twice or three times a year than to be fuming every time I have to touch files in my project.
This is about as useful as "A monad is just a monoid in the category of endofunctors."
It's basically a lot of words which make zero sense for a user starting to use git -- even if it happens to be the most succinct explanation once they've understood git.
> The base abstractions are minimalist and easy. The things you want to do with them are elaborate and complicated. Learn the former, google the latter.
You can't really learn the former -- you can't even see it till you've experienced it for a while. The typical user groks what it means after that experience. Correction, actually: the typical user simply gives up in abject frustration. The user who survived many months of using a tool they don't understand might finally be enlightened about the elegant conceptual model of git.
Facetiousness aside, the things you do often, you learn once and you don't really have to remember/think when doing them. Most of the esoteric operations are mostly unnecessary to burden yourself with until you actually have to do them, when you just read the documentation.
1. Git is complicated 2. Perforce is so simple to use that I can teach an artist or designer who has never even heard of source control how to use it in 10 minutes.
Then you came in and said the way Perforce handles read-only files is stupid. You know what, I agree! That's a solvable problem. If Perforce wasn't acquired by a private equity firm maybe they'd actually work to make it better. Alas.
This isn't about Git vs Perforce. I post in all of these Git HN threads because I desperately want people to realize that Git sucks ass and is actually really bad. WE COULD HAVE SOURCE CONTROL THAT DOESN'T SUCK. IT'S POSSIBLE. I'm not saying that Perforce is that solution. I'm saying that Mercurial and Perforce are existence proofs that certain things are possible. Source control doesn't have to be complicated! It doesn't have to have footguns! It doesn't need a 189 page guide!
Thank you Beej.
The command line isn't that hard to use if you've ever used the command line before. Beginners trying to learn git and command line at the same time (which is very common) will get utterly confused, though, and for a lot of beginners that's the case. The only difficult part with git over the command line is fixing merge conflicts, I'd recommend anyone to use any IDE rather than doing that manually.
No IDE will be of any help for getting back to normal when you get into a detached HEAD state, which IDEs will gladly let you do if you click the right button.
In my experience people come to git and start using it with the centralised paradigm in their heads: that there is one repo and one DAG etc. They think that their master branch is the same as "the" master branch. You just can't get good at git with this wrong understanding.
The issues most people seem to have with git are common version control issues. Version control is actually hard, even if it's just "what has changed", once you start going beyond two users editing a file at once. When three people edit a file at the same time, there's going to be complexity when those changes need to be applied back, and that's where you start getting into branching/merging/rebasing.
Just like some people simply cannot get functional programming/object oriented programming/imperative programming to click in their head, others will never truly grasp version control. It's a paradigm of its own. People who know lots of data structures like to trivialise version control into data structures ("it's just a list of ...") but the data structures are the chosen solution, not the problem.
Another complexity issue is that git is actually pretty smart, and will fix most problems automatically in the background. Often, when you need to manually operate on a git repo, you're in a situation where git doesn't know what to do either, and leaves it up to you as the expert to fix whatever is going on. And frankly, most people who use git are nowhere close to experts. The better Git tooling gets at fixing these situations for you, the worse your situation will be once you need to manually correct anything, and the worse your perception might get.
I have no good advice for you on how to work Git better. All I can say is that I'm very productive with Jetbrains' IDE integration, others seem to prefer Visual Studio Code's git integration, and then there's the Tortoise people. Find whatever tool works best for you and hope you'll have a random epiphany one day.
And then when everything works, compress commits into a few big commits with squash, and actually try to merge that back into the main branch.
> I might start writing a new function, decide that I want it to be a class only to give up the class and wanting to return to my almost complete function.
For me, that would easily be three commits in my dev branch (one with a first implementation of the function, one with a refactor to a class, then another one back to a single function) and when the function is finished, one squashed commit in a merge request. If everything goes right, it's as if the class file was never there.
It has to be said, relying on squashing doesn't work well when you're working in a team that doesn't pay too close attention to merge requests (accidentally merging the many tiny commits). You also have to be careful not to squash over merges/use rebase wherever possible so your squashed commits don't become huge conflicts during merge trains.
When I work on my own stuff that I don't share, I don't bother squashing and just write tons of tiny commits. Half of them leave the code in a non-compiling state but I don't necessarily care, I use them as reference points before I try something that I'm not sure works.
There is something to be said for carefully picking commit points, though. While finding the source of a bug, git becomes incredibly powerful when you can work git bisect right, and for that you need a combination of granularity and precision. Every commit needs to have fully working code, but every commit should also only contain minimal changes. If you can find that balance, you can find the exact moment a bug was introduced in a program within minutes, even if that program is half a decade old. It rarely works perfectly, but when it does, it's a magical troubleshooting tool.
I know programmers like everything to be in version control, but AI models and git just aren't compatible.
If you insist on memorizing commands for all these tasks (of which there are many), indeed, you're going to struggle and decide you need a 30 section guide. But you don't, and want to whine about it.
> I don’t even disagree, just wanted to say fuck git, I guess.
Pretty much.
"Let's say you modified foo.txt but didn't add it. You could: <git command>"
Followed by:
"And that would add it and make the commit. You can only do this with files you added before."
Wait, what? So, I modified foo.txt but didn't add it, and then the command to add and commit at the same time can only be done with files I did add before?
Guide was working great to heal years of git trauma up until that point though!
A powerful Git GUI makes even moderately-complicated actions like cherry-picking, interactive rebasing, and even ref-logging absolutely trivial. In fact it was precisely said GUI tool that allowed me to develop an intuition for how Git worked internally; the CLI does no such thing.
Unfortunately it's been long enough I don't remember details why, just that it was something with how it handled branches.
That is, to set your upstream branch to the branch you want to merge into, aka the integration branch. So instead of setting upstream of "feature/foo" to "origin/feature/foo", you would set it to "master" or "origin/master".
This simplifies a lot of things. When you run `git status` it will now tell you how far you have diverged from the integration branch, which is useful. When you run `git rebase` (without any arguments), it will just rebase you on to upstream.
Setting `origin/feature/foo` to upstream is less useful. Developers tend to "own" their branches on the remote too, so it's completely irrelevant to know if you've diverged from it and you'll never want to rebase there.
If you set `push.default` to "current", then `git push` will do what you expect too, namely push `feature/foo` to `origin/feature/foo`.
Why isn't this a more common setup?
I find this an odd statement. I mean, no, I don't want to do the work! Not if it isn't necessary in the first place.
Take staging (or the index, because another of Git's foibles is poor naming conventions that stick around and confuse newcomers). It's kind of a commit, right? In the sense that it's a snapshot of work that represents a change to the code. Except we can't really make it behave like a commit, we have to interact with it using special commands until we turn it into a commit. Are these special commands really doing much differently than we might do with another commit? Not really.
Or take stashes. Stashes are more like commits — they even appear in the reflog! But they also aren't real commits either, in the sense that you can't check them out, or rebase them, or manipulate them directly. Again, you need a bunch of extra commands for working with the stash, when really they're just free-standing anonymous commits.
Or take branches. Branches are, as everyone knows, pointers to commits. So why is it important whether I'm checking out a branch or a commit? Why is one of these normal, but the other produces hideous warnings and looks like it loses me data if I haven't learned what a reflog is yet? And if a branch is just a pointer, why can't I move it around freely? I can push it forwards, but I can't move it to another arbitrary commit without fiddling around a lot. Why?
Or take tags, which are like branches, but they don't move. Is "moves" and "doesn't move" such a deeply important distinction that Git needs branches and two different kinds of tag?
---
To be clear, I think Git is a good tool, and I agree that once you've started to familiarise yourself with it, it's not so complicated in day-to-day usage. Yes, you'll probably need to Google a few specific commands every so often, but the general UX of the tool has significantly improved since the early days, and it is getting better.
That said, I also don't like the idea of settling with Git just because it's good. If there are alternatives out there that can do everything that Git can do, but with a simpler conceptual model, then I want to try them! (And, spoiler alert, I think there are better alternatives out there — in particular, I think Jujutsu is just as powerful as Git, if not more so, while simplifying and removing unnecessarily duplicated concepts.)
It has this idea of mutable commits, so essentially you can check out a commit, and then whenever you change a file, the commit is updated with the new file contents. Then internally, whenever a commit gets changed (or any aspect of the repository) that gets recorded in an append-only log. At any point in time, you can scroll through that log and restore any previous repository state, including changes to individual files.
By default, Jujutsu does the snapshotting thing (i.e. updating the commit with the contents of the local files) every time you run the `jj` command. However, you can set up file watchers so that it does the snapshotting every time a file changes in the repository. If you do this, you should be able to browse through the op log and see all of the changes you've made over time, including reverting to any of those stages when necessary.
In fairness, I've not tried the file watcher thing out personally, but being able to review the op log is fantastic for trying to go back to previous versions of your repository without having to do teeny-tiny "wip" commits manually all the time.
Interestingly that is exactly the opposite of my experience. Git is a practical tool with practical appeal to people who want to do practical things. Egghead gedankentheorists hate it, as evidenced by this very subthread.
In point of fact I find the ability to accomplish workaday tasks with git to be a far better predictor of someone's success as a developer than stuff like being able to recite Rust minutiae. People who like git are people who like getting stuff done.
in my experience, strong writing and communication skills are one of the best ways to stand out as an engineer -- and your articles are maybe the best example of this out there. keep on setting a great example for us. :)
Also, reusing branches for GitHub pull requests (vs. creating new branches for each PR) might warrant some discussion in section 17?
I don't think "git checkout" is considered the "old alternative", at least not yet. Last time I checked, `switch` is still experimental, I haven't even considered moving away from the workflows/commands I first learned when I picked up Git ~15 years ago. Everything I want to do still works exactly the same (`git checkout` still does the exact same stuff as before), and I'm able to collaborate with everyone else using git, why change workflow then?
It's really simple, much more than what we think at first. I explained it myself here, in section "three-way merge": https://lucasoshiro.github.io/posts-en/2022-03-12-merge-subm...
There are plenty of other explanations out there if mine isn't enough clear for you, just google "Three-way merge".
> blend two functions or whatever and it "works."
It's purely based on find changes and it doesn't check the syntax. If the commits has been merge correctly is responsibility of the programmer.
Look at this valid Python code:
if a == 1:
foo()
bar()
If a branch deletes foo() and other branch deletes bar(), it will merge to this invalid Python code:if a == 1:
In Python we can't just leave empty blocks, like C or Java. In Python we would need to use "pass":
if a == 1: pass
So yeah, there are cases that merge doesn't work because Git operates over data, no matters too much what information they hold
What I'm curious about though, since I basically entered the software developer workforce just as Git became mainstream and GitHub became popular, how would you do those things with the alternatives at the time; SVN, Mercurial, Perforce and the rest? Would it be easier or harder? Would it work better/worse in a sync/async context, without centralized servers?
There are lots of people complaining about how needlessly complicated git is, but they almost always fail to put forward some simpler alternative that can handle the same things. Is git actually accidentally complicated or purposefully complicated because the topic at hand is kind of complicated?
You can switch branch also with ‘git checkout’ and you just ‘git stash’ your changes.
‘git reset’ is fine to reset files, but again if you just want to ”clean” repo you can stash.
You can reset staged files again with ‘git reset’
Mo idea why you would want to checkout a random commit and the start committing from that, but you can also just ‘git reset --hard HEAD~x’ where ‘x’ is number of commits you want to go back. Hard is optional, but I assume that is what you want based on your comment.
Depends on the change. If you change different lines there will be no conflicts.
This is all basic stuff you should know if you are developing code with other people
What a stupid series of sentences this is for a piece of software we have to use daily. Even talking about it feels cringe.
Even though SHA-1 collision were achieved, they are impractical and we can make the assumption that "if two objects has the same hash, they are the same".
To have a cycle, both commits involved would need to have the hash of the other, which is impossible: the hash of a commit is based on its content, its content contains the hash of its parent.
We could only have a cycle here if we create two commits created after two arbitrary hashes.
Git is only a directed graph with the adjacencies stored as hashes. Everything else is just tooling around that data structure. No problem using Google to find the commands (the Git CLI is very inconsistent...) but if you know what you want to do with that data structure you can find precisely the commands for that.
The proof that there are really no branches in git's storage is a simple task that's not achievable in git:
suppose you had some branch, but you don't remember it's name, then you branched off and issued some commits. Now there's no way to get a git history consisting of just the commits introduced since you branched off.
Whew, just from the intro this feels like a breath of fresh air. Probably gonna migrate to it right after finishing the tutorial. Thanks for mentioning!
It is _exceedingly_ hard to lose files in jj, it's actually emotionally frustrating reading the line "most important thing [..] is to never ever delete file" because that's the whole shtick in jj with the oplog and whatnot - so something like nuking secrets completely from a jj repo is a bit of a chore.
Can you file a bug at least? A repro of some sort?. Or at least show us what is it what you did, `jj op log` might be enough to deduce what happened.
Also check out `jj op log -p`, your files might very well be in history, especially if, as you said, jj status took a long time (presumably snapshotting those files that got lost)
if they're allowed to push somewhere and make it someone else's problem, that's not their fault
What? This made zeroest sense of the day. Like, I should walk to their desk and check if a feature branch is okay to push or what?
After 10 minutes, the person unfamiliar with Perforce, will not know how to deal with read-only files. No chance of that happening.
Because Mercurial was dreadfully slow at the time for anything as big as the Linux kernel tree. Linus also put his thumb on the scale because he was the author and still the primary maintainer of git at the time, so he could bend it to whatever shape he wanted without needing to ask anyone else. Not really a knock on Linus, I'd do the same in his position, but it does explain much of its advantage.
Here are some examples:
We have some repositories that are created and maintaned by scripts, mostly for CI purposes. The scripts have to deal with various aspects of how checkouts, commits, automatic rebases etc. are done. For example, I had to write a script that automates "git-rebase -i" (simulating the editor, parsing the contents of the file that git generates in order to configure the rebase etc.)
Another example: generating various statistics for the repository (again, automatically). This is something we used to do to analyze the situation with build servers: how many do we need, how to load-balance them etc.
Another example: automated builds, where the build system needs to integrate with Git, extracting necessary info, rebasing, committing, parsing commit messages for guidance etc.
> rsync
What I mean by this is that most programmers use Git as an append-only database. And, by and large, aren't bothered by the state of the history, never utilize the history for anything. As long as they are all able to access the source code in some sort of sane state, they are fine.
This creates a lot of problems for the automation / infra / release people because they want history to have certain properties, which are lost if it's treated as append-only log, but usually our pleas are ignored if they are even heard.
Having to add P4 support to any script, sucks. Having to do a network operation when touching files, sucks. Many many many apps have no idea what p4 is and will never get p4 support.
Git gets out of the way.
The other issue you ran into with ignored files becoming tracked is a known limitation. I agree that it's really annoying. We have talked about it many times before but we didn't have a proper issue for tracking it, so I created one now: https://github.com/jj-vcs/jj/issues/5596
A good git gui works as well as p4v (and usually far less buggy).
The major difference in my eyes is that p4 can enforce more settings from the server. It's easier to get artists set up in p4 than git.
> There's a reason that like 105% of AAA game dev uses Perforce.
Irony of ironies, Unreal is distributed with git but largely uses p4.
P4 is dominant but I feel like a lot of that is momentum. Making a Unity game with git is pretty easy. Some Unreal tooling is built around p4 only but not really for any technical reasons.
Edit: Does anyone know a good way to convert one of the HTML pages into an epub for reading on an ereader? The PDFs will definitely work, but wanted to see if anyone knew of any tools for HTML -> EPUB conversion.
Wild.
File locking is one of the reasons why vanilla Git is not that popular in game dev. It only exists with Git LFS and it is not really easy to use or reliable.
1) The fact that "fetch" doesn't happen automatically in the "chrome" commands.
2) naive use of "git merge" results in history that's a cyclopean horror. For example, caring about the "left" and "right" parents of a commit.
3) rerere isn't enabled by default so if you're merging from upstream constantly you're having to re-resolve same conflicts, every time is an opportunity to screw up.
4) a culture of keeping a clean history but cleaning history is destructive and painful for other users of the same branch.
5) git merge merges from local (stale) branch by default, so when merging from upstream to get new commits you have to remember to `git merge origin/main` instead of `git merge main`. Also see (1).
6) using submodules. At all.
You can reset staged files again with ‘git reset’
To "revert a file to what was staged" you have to "git checkout" again, it seems, not "reset".
This is all basic stuff you should know if you are developing code with other people
Yeah. It seems that it is basic, until you try using it for something that is not quick one-shot patching of "append-only" code.
Try downloading the single-page html and coverting with pandoc:
pandoc index.html -o bla.epub
Maybe it needs some fine tuning, but the result seems good to me.
Yes. I use it every day. I've ran P4 servers that serve hundreds of GBs per day globally with both commit edges and regular proxies. I've written batch scripts, bash scripts, and tooling in python, go and C# around it.
> Having to add P4 support to any script, sucks.
I disagree. It's no worse than adding git support to something. p4 zTag isn't the most elegant thing, but it works.
> Having to do a network operation when touching files, sucks.
Does it? Is it any worse than having to keep the entire history of every file locally on your machine, including any "large files?" And git-lfs as a solution to that means you're now coupled to wherever those files are stored. Making large submits to P4 isn't the nicest experience, but it sure beats paying that price every time you clone a repo IMO.
> Many many many apps have no idea what p4 is and will never get p4 support
In the same way that many people in this thread are blaming a git gui for a problem, "that's not P4's fault". I do agree it's shit though.
> Git gets out of the way.
Until it doesn't.
Losing your work should be exceptional. It's very, very easy to fuck a rebase up, and rebasing is (like it or lump it) a common operation. You shouldn't one step away from an exceptional case from a daily operation.
Git is complicated _beacuse_ of this. The defaults are tuned for this. But, most people don't need this. I'm sure there are people out there who set an upstream to their coworkers PC and clone a branch from them, merge it with their work and then someone else takes that and is saved a bunch of work because the commits all line up, but for every 1 of those people there are probably 100,000 who push and pull to a centralized forge, and pay the complexity cost for the distributed workflow.
> but they almost always fail to put forward some simpler alternative that can handle the same things. Is git actually accidentally complicated or purposefully complicated because the topic at hand is kind of complicated?
Git is complicated because it's got poor defaults, an unintuitive cli, and is designed for distributed workflows (I've never worked anywhere that has used a distributed workflow, fwiw). I can sit someone down with perforce for 15 minutes and basically never have to interact with them on it again. It's _so_ much simpler - because it's centralized. It has some baggage, is definitely not perfect (and it costs an absolute bomb). Mercurial is another example of something that is much, much easier to use and work with. I wish mercurial won, honestly.
All that said, they are really useful. And, honestly, the chapter would be pretty short to get basic usage down... but also if you've gotten as far as grokking how branches work, it's pretty easy to pick up worktrees. The fact that lots of people don't know they exist is points for adding it just for that reason alone.
I'll mull it over. :) Cheers!
[1] https://www.koyeb.com/blog/herokus-free-tier-legacy-the-shou... [2] https://blog.gitbutler.com/why-github-actually-won/
I used to work for a large company in the ops department, where a significant portion of my day was spent walking between cubicles and fixing the dev. environment of Intellij IDE programmers. Most of them didn't even know how to find the project they worked on in the filesystem w/o using their editor. The tantalizing task of opening a file with unknown extension was way too much to ask etc.
They would often mess up something in the version control too, using Intellij integration tools, which are really, really bad. But, I don't know whom to blame in this instance. Both the user and the tool were of extremely low quality.
So, if, eg. their Maven build had some sort of an interaction with Git, and they messed up something in their local repository, all work would come to a grinding halt, because they had no idea how to even begin to understand what went wrong.
It's a kind of job where you begin to lose faith in humanity very quickly :D
1. The margins are offset in two-sided, alternating pages. 2. The page numbers are justified alternately left and right in two-sided, and the page header differs left and right. 3. Sometimes a blank page is injected with two-sided to make a chapter start on the correct side of the book.
Right, but since git specifically was made for usage without decentralized servers, that complexity isn't accidental, it's purposeful as without serving that particular use case, git isn't really git anymore. Most design decisions in git comes from having to serve that use case, for better or worse.
> . It's _so_ much simpler - because it's centralized
Right, but that's also a poor comparison. A bit like saying that `mv` is much simpler than `rsync` because `mv` always move files locally. Yeah, that's true, but the entire point of `rsync` is to do remote sends/receives, so compared it to something that cannot, kind of ruins the comparison.
But yes it does literally include that. Perforce is THE standard tool for gamedevs. It’s not hard.
Though I have to say, for your examples (generating statistics and automated builds), read-only operations generally suffice for me, aside from pushing tags. I prefer to implement pull-based deployment if possible, and only allow release branches to fast-forward.
Now svn does have things I miss from the Mercurial world.. grep --all, fa --deleted, revsets, phases.. some could be implemented serverside in svn, but svn dev lost a lot of momentum post-DVCS (git esp).
But DVCS has issues that aren't an issue in svn land. History consistency, simple reliable narrow/shallow, people can work on files independently without syncing. (and a significantly more complex dvcs process)
With GitHub being the top platform for sharing source code and as the top choice for the basket of all our eggs, I'd wager we need DVCSs more than people need or appreciate today. And that's just considering how often GitHub is down today.
If we start to emphasize with people who have really shitty internet connections (which is a larger part of the world than you seem to think), we can start to understand why it's really useful to be able to share our code with our co-workers on our local network without having to rely on terrible, minimum 5s latency connections to US companies who basically don't care about you.
That's the thing. For most developers, it's not, and it doesn't. I have never needed a VCS that couldn't be wrapped in a few batch files like add.bat, get.bat, put.bat, diff.bat, merge.bat, and list.bat. You can do the same thing with git, of course, but just understanding enough about it to write the batch files practically takes a semester of study.
Unless your job is to maintain the Linux kernel, git is probably not the right tool for your job. But it 'won the source control war', so... git, it is.
Note: centralized does not mean you can’t work in offline mode or share basic deltas
There are two things I suggest as workflows for people when I teach them about rebase workflows.
> Since rebase “replays” your commits onto the new base one at a time, each replay is a merge conflict opportunity. This means that as you rebase, you might have to resolve multiple conflicts one after another. ... This is why you can conclude a merge with a simple commit, but ...
For multiple conflicts on several commits being replayed, if it's _not_ useful to go through them all one at a time, I suggest that people do a squash first rebase from the fork point (which by definition can not have conflicts) to collapse their commits into a single commit first, and then rebase again from the branch.
For instance, if forked from main:
git rebase -i `git merge-base main --fork-point`
Squash all of those, and then as usual: git rebase -i main
Second, when rebasing repeatedly onto an evolving branch over time, you'll often find yourself resolving the same merge conflicts over and over again."rerere" (https://git-scm.com/book/en/v2/Git-Tools-Rerere) will allow git to "reuse recorded resolution" so that you don't have to do them manually each time.
My gitconfig for these:
[alias]
forked = "!f() { git merge-base $1 --fork-point; }; f"
squash-first = "!f() { git rebase -i `git merge-base $1 --fork-point`; }; f"
[rerere]
enabled = true
However I'm seriously thinking about patching something together by grabbing appropriate bits of this.
They are real commits, you can check them out (it detaches your HEAD, the syntax to reference them is `stash{N}`). Although I think this furthers, rather than undermining, your point that there are an unnecessary number of other commands to work with the stash.
I think this is a failure of the git CLI as much as the internal data-structures. I think the idea of a commit tree is very good and a lot of people recognize that. The commands that git exposes to work with that tree can sometimes be miserable.
Yes, network traffic does suck more than spending extra disk space, especially when you need multiple workspace because P4 sucks at switching anyway.
I don't understand what you mean about cloning. If you set up LFS properly it's not much worse than a fresh P4 pull.
But compare "git switch X" and "git restore X". This makes different things look different, and obvious, which is usually a valuable thing when learning a new tool.
And I completely agree that this is about the CLI more than the internal data structures. I pointed at Jujutsu earlier, and that uses Git as the underlying data store (at least in its default configuration). It's an effective strategy in large part because Git-as-a-data-structure works really well already, and the distributed aspect means you can interop very effectively with existing tools like Github just by speaking the right protocol.
But while it keeps much of the same data structures, Jujutsu exposes a very different interface to those data structures, and one that I think is significantly simpler in large part because there aren't so many special cases (such as commits vs staging vs stashes vs ...). You end up with a smaller set of commands, but those commands are more consistent and can be applied in more cases. And you still have staging and stashes, it's just that you can build those yourself more naturally out of the tools that Jujutsu gives you.
I usually refer people to https://cbea.ms/git-commit/.
> But in this section we’re going to be talking about a specific kind of merge: the fast-forward. This occurs when the branch you’re merging from is a direct ancestor of the branch you’re merging into.
Looks like "from" and "into" are swapped: "main" is "into" there, "newbranch" is "from", and "main" is a direct ancestor of "newbranch".
Without your tutorials I’m not even sure if I would have chosen the carreer I did- thank you for all the love and effort you put into your posts; Im sure that there are many other people who you’ve touched in a similar way
I've also blogged about it
- https://looselytyped.com/blog/2014/08/31/gits-guts-part-i/
- https://looselytyped.com/blog/2014/10/31/gits-guts-part-ii/
Happy to get any feedback.
Section 5.1 (https://beej.us/guide/bggit/html/split/branches-and-fast-for...)
> The default branch is called main.
> The default branch used to be called master, and still is called that in some older repos.
This is not true. Git still defaults to `master`, but allows you to change the default (for future `git init` invocations via `git config --global init.defaultBranch <name>`)
See https://github.com/git/git/blob/bc204b742735ae06f65bb20291c9...
Again, thank you. If I find anything else, I will be sure to post here.
*Update*: I also feel that referring to "older repos" sends the wrong message. *GitHub* decided to make this change, causing others to follow, and finally Git itself allows for the aforementioned configuration, but it has little to do with _newer_ or _older_, but rather preference.
Right! People often forget git was designed specifically for Linux kernel development which is done by a loosely-knit global base of developers. There are much simpler solutions if you can actually live with exchanging USB sticks.
One nice thing is only needing to know one tool for both open source and centralised development, though. It can seem a little odd if you don't do any open source at all, though.
> hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and 'development'. The just-created branch can be renamed via this command:
That's going to make it more "interesting" to write the fix, that's for sure.
Thanks!
So really you can choose whatever suits your needs.
Personally the things I love about mercurial are:
more consistent commandline (that's the simple part others bring up)
revsets (awesome query language for revisions, there's also filesets, but I don't use that as much)
absorb (I think someone added a git extension that does something similar a few months ago)
fa --deleted
grep --all
phases ♥
So in figure 5.4 you say we merge 2 commits into a new one and somehow both branches point to new commit. This will definitely confuse people new to git.
I'd say it's better to write we merge anotherBranch into someBranch and leave the former where it is. Same for the next merge.
Just a suggestion
yes, to understand an application, you must also understand the underlying data structures, architectures, models, use cases -- i am not sure what there's to roll eyes at. but there's no requirement that says that understanding has to be deep in order to work on it, or use it.
i think if you treat it like cleaning a large room, by picking out one corner at time and focusing on cleaning that before moving on, you'll find that the room is cleaned in no time, and git isn't anywhere nearly as complicated as it may feel.
there is absolutely no reason to digest a guide this dense for use-cases in every day production settings, bc those usages only make up about 10% of what this guide covers.
yes, learning things can be overwhelming, challenging, full of darkness and terrors, but that's what learning is, until you've learned.
but here is the catch imo: once you've learned, you don't stop learning and the challenges don't go away. you just become better at navigating the darkness, bc you get better at learning and managing feelings of overwhelm and confusion which are by products of complexity -- real or perceived or both.
jump in. it ain't that scary, even if it feels scary. i promise. i've been there, and you can overcome it.
in my 8 years of using git as a primary tool for vc, i have not once run into confusion on how to switch branches, create branches, prune branches, sync remotes with locals, and other common workflows.
does that mean i have only dealt with simple merges or haven't fucked something up bc i did not understand something and made things way harder than necessary (merging/replaying 50 commits vs squash rebase workflows, for example).
and no, you don't need to 'fetch' before you switch, fetching is only relevant if you're needing to bring in remotes or you're preparing for merges etc.
someone committing bunk to a main branch or something considered a production branch is not a git problem -- that's just bad development practices, and the onus is on the developer there to not do that and to understand why it is bad.
as for your other complaints, these are much more easily managed when the developers are not just arbitrarily commiting to branches without any strategic thought, but to point out, a lot of those problems are solved via working with commit hashes and branching, assuming you have already plugged the leak that is committing breaking changes to a main branch.
why are breaking changes that are mega changes even making it through to main?
you don't have to treat rebases or merges as this black hole of "i have no recourse for not getting it perfect the first time".
Let me see if I can do that and save the clarity.
Are you concerned that your git exposition is much longer than the other guides you have produced?
This is just asking for trouble.
((cd /tmp/t; find . -type f -print) | sort | while read f; do cmp -s {/tmp/t,/tmp/t1}/$f || vim -f -d {/tmp/t,/tmp/x1}/$f 0<&9 || break; done) 9<&0
Typing ^C to vim doesn't get you very far, so if you make a mistake causing the loop to return 1000's of files you are in for a bit of pain without :cq. The :cq triggers the break, exiting the loop.