[HN Gopher] Git In Two Minutes (updated after 8 years) ___________________________________________________________________ Git In Two Minutes (updated after 8 years) Author : garyrob Score : 193 points Date : 2022-08-06 18:03 UTC (4 hours ago) (HTM) web link (www.garyrobinson.net) (TXT) w3m dump (www.garyrobinson.net) | ArrayBoundCheck wrote: | I wish they made a breaking change in the next version and make | the CLI actually usable. | | Before you downvote, ask yourself how do you list tags, branches | and remote | mmcclimon wrote: | While acknowledging that git's CLI is often unintuitive: `git | tag` lists tags, `git branch` lists branches, and `git remote` | lists remotes, so I don't think I understand this particular | objection. | ArrayBoundCheck wrote: | Compare it with `git branch -a` and `git remote -v`. That's | my point. Not only are they all different flags but you'll | get half the data you could be getting and not know why. It's | impossible to google | umanwizard wrote: | They shouldn't break the existing `git` command as it is widely | used in scripts. But there are projects that try to build | better UIs on top of git; the most serious such attempt that I | know of is magit. | ajross wrote: | "git tag", "git branch -a", "git remote -v" | | You point is what, that these are needlessly asymmetric? It's | true. But they're in my head because I do them every day, and | it's not like I'm suffering under the burden of remembering a | handful of flags. That's a pretty far cry from "not actually | usable", so maybe your hyperbole is a little misplaced? | ArrayBoundCheck wrote: | Correct. That was a simple example that's easy to understand | | Anyone with half a brain can understand that if they can't | keep something as simple as printing a list consistent you | better believe nothing else will be straightforward. Which is | my point. NOTHING is straightforward and I haven't met a | single person who likes the CLI if they do anything more | complex than a commit, push and pull. I know people who still | refuse to use rebase and don't understand bisect or blame. | They use a GUI to restore files | PeterWhittaker wrote: | Branches are easy, what with them being only labels: | | > git branch --all | | Tags are different, since they are actual objects in git, but | using ls-remote isn't tough, and one could create an alias. | probably_wrong wrote: | > _it it's enough be useful for beginning solo developers, and | provides a start from which you can grow._ | | I like this guide a lot as a cheatsheet. However, when it comes | to beginners I fear it is one of those things that make sense | only when you already know what the guide is talking about. | | It would take me more than two minutes just to explain a | completely new developer what a commit is and why they would want | one. And God help us if I throw the output of "diff" at them | without warning... | | The sad truth is, you cannot explain git in two minutes. I | nonetheless admire the author for giving the problem a fair | fight. | spaceman_2020 wrote: | as a noob trying to pick up coding just to experiment with some | ideas, I always found Git to be surprisingly confusing. I feel | that a lot of the command names aren't very intuitive. | | Or am I just an idiot? | garyrob wrote: | I agree with you. What I do is use the snippets from the blog | post without particularly thinking about them! | sedatk wrote: | Git is confusing. Alternatives like Mercurial are way more | intuitive and easier to use, but they lack popularity. | umanwizard wrote: | I don't know whether you're an idiot or not, but thinking git | is confusing is certainly not evidence to that effect. | | Git _is_ confusing; it became the de-facto standard because it | was the first free DVCS (and DVCSs solve lots of problems that | were common to old non-distributed VCSs), not because its UI is | particularly well-designed. | kadoban wrote: | Git's command names, and UX in generaly, is its worst area. | It's definitely not just you. | | Many professional software devs I work with still really have | no idea how git works, they've just memorized the 3 or so | commands they absolutely need and maybe how to recover when | something out of the ordinary happens. | probably_wrong wrote: | When it comes to git, I am firmly of the opinion that it's not | you, it's them. | | Git is simple, but it takes a lot of experience to appreciate | its simplicity. So don't beat yourself up, git is _hard_ and it | 's okay to be lost. | sureglymop wrote: | I think what makes it more confusing is that the inner workings | are almost too simple.. so one wonders why there are so many | commands etc. | | Git is basically a linked list (if you have one branch) and a | graph (if you have more than one branch). Then all you are | really working with are _pointers_ to certain nodes in that | graph. | | In git terminology these nodes are called objects and there are | different types of objects such as tree objects and commit | objects etc. Objects are compressed with a library called zlib | and are stored as files within the .git/objects directory, the | file name is the hash of the decompressed object. | | But, back to the graph and the pointers to certain nodes. A | branch itself is nothing more than a pointer either. You can | look at the files in .git/refs/heads to see where they point. | | Now, what you do with git checkout is changing the node you | currently view in the graph. If you make a commit you create a | new node. Merging is nothing more than taking two nodes and | creating a new node that is connected to both of them. | | The main problem i think is that concepts like branch, tag, | commit etc are actually just overcomplicated abstractions of | the much simpler graph nodes and pointers and are thus | confusing. | jonnytran wrote: | Git isn't designed for "noobs trying to pick up coding just to | experiment". It also isn't really designed for solo developers | as the OP is about. | | Git is designed for collaboration. Git's UI is absolutely | unintuitive, especially coming from other version control | software. But that's irrelevant. Everyone wants to use it | because of the network effect. | | In terms of _why_ the UI is unintuitive, I believe it's because | it intentionally exposes its internal representation. Unlike | its predecessors like subversion, Git has infinite flexibility | in terms of the workflow that teams of people can adopt. But | the flexibility comes at the cost of learning how to use a | distributed graph of commits. | | Personally, I never learned git by reading recipes of commands, | like the OP. I only really grokked it by understanding how it | works internally. This article helped me: | | Git for Computer Scientists https://eagain.net/articles/git- | for-computer-scientists/ | COMMENT___ wrote: | > Git has infinite flexibility in terms of the workflow that | teams of people can adopt. | | IMO flexibility is just a meaningless buzzword used to | describe overly complicated and poorly designed products. If | a product has crappy UX, they just call it "developer | oriented" and "flexible". | | When I read about "flexibility" of a software product, I | think that this product is of low quality. And that I will | have to spend some time to make it work for me (hours? days? | weeks? years?). To me as a user this flexibility does not | matter at all. | | The product either works or it doesn't. If it works, I don't | want to spend a career to learn its internals. I just want it | to support my use case and give clear step by step | instructions in its documentation. | | I better spend my time on something more important than | exploring how this or another crappy software product is | flexible. | jimbobimbo wrote: | I have 20+ years of professional experience and I'm using git | via Visual Studio or VSCode UI. I'm not feeling ashamed of | that. | ducktective wrote: | obligatory `lazygit` plugging. I do this because this project is | criminally underrated: https://github.com/jesseduffield/lazygit | garyrob wrote: | About 8 years ago, I blogged a very brief guide to using git for | a solo developer. A lot of people seemed to like it. | | A couple times since then, I've noticed there was something I was | using that wasn't in it, but that could be added without making | it significantly longer or more complicated. So there were a | couple of updates. | | I did another one today, and had the thought that since this | guide now includes the benefit of 8 years of practical experience | in actually using it, while still essentially being "Git In Two | Minutes", it might be worth posting to HN. So here it is. | | It doesn't say anything about github. It really is for a solo | developer who wants to start using git in a very painless way. | With the additional goal that you can profitably use git for | years without going beyond the described features. | | https://www.garyrobinson.net/2014/10/git-in-two-minutes-for-... | noja wrote: | Without switch and restore, it is not modern git! | boredemployee wrote: | thank you very much. I'm always reluctant to read/watch _any_ | git tutorial, I think that will help me a lot! | garyrob wrote: | I hope it does! | notRobot wrote: | Thank you for this! | moritonal wrote: | Hey, just a heads up (won't be a problem for most people | Goolging git) but on mobile (Firefox) the code blocks are | almost unreadable because they're so small. | boustrophedon wrote: | In both examples given in the "Undoing a bad commit" section | (fixing a commit message and fixing an error in a file) it's | easier to make the change and then run `git commit -a --amend` | which takes the current changes you have and adds them to the | last commit, allowing you to change the commit message as well. | | There are other cases where git reset is useful, but generally | not for the reasons given. | carom wrote: | How does this not mention git push? That and pull seem a lot more | essential than everything that came after commit. | nmz wrote: | Absolute crap article. | | You don't learn git in two minutes if you don't talk about rebase | and remotes. | | You want to learn a dvcs in 2 minutes? try fossil. | demarq wrote: | Guides like these are an absolute treasure when on-boarding | junior devs. | | It can be really difficult distilling all you know about a | certain topic into something short and concise like this. | malkia wrote: | Hey not only junior developers - there are senior ones (like | me) that need it too! So thanks for all these "one-pagers" that | are easy to remember. | demarq wrote: | haha but of course! | candiddevmike wrote: | Why do they have '--' as an argument in a lot of the commands? I | don't think that's necessary? | PeterWhittaker wrote: | To quote TFM: | | > This option can be used to separate command-line options from | the list of files, (useful when filenames might be mistaken for | command-line options). | | This is a common idiom, e.g., to grep a file for a pattern that | matches a grep argument, | | > grep -- -e file | | Edit: fixed dash weirdness. | gizmo686 wrote: | It forces git to intereperet what comes after as paths. | Normally this is not needed, but occasionally you get a | filename that causes ambiguity. | | For instance, "git checkout test.c" will check out the file | test.c unless you happen to have a branch called "test.c". (See | also people complaining that checkout is overloaded". | | Simmilarly, "git add --verbose test.c" will add test.c, and log | that to stdout. "git add -- --verbose test.c" will add test.c | and --verbose, where "--verbose" is the name of a file. | | This isn't git specific, most CLI tools use "--" to restrict | the parsing on arguements that follow. | soupshield wrote: | What do we call the "--" part in a command like this: | git checkout HEAD -- <filename> | | I find it hard to remember things unless I understand their | purpose. It looks like it's specifying an argument but without an | argument name (e.g. --verbose), unless it's similar to a pipe | | symbol and <filename> is being passed to the checkout command as | some special kind of argument? | swordbeta wrote: | https://unix.stackexchange.com/a/11382 | ttymck wrote: | It is a delimiter indicating the end of options: | | https://unix.stackexchange.com/questions/11376/what-does-dou... | gizmo686 wrote: | I don't know what it is called, but it forces what comes after | to be interpreted as a filepath. | | This is not git specific, but a common convention for CLI | tools. Try running: > touch -- -i foo | > rm -- -i foo | | And compare what happens without the "--". | soupshield wrote: | Thank you for this brilliant explanation (complete with | interactive example :) I completely get it now. | pojzon wrote: | Not only a filepath, this means pass anything past "---" 'as | is' as an input and not an option flag. | | docker run -it nginx --- ls la | soupshield wrote: | Ah yes I've seen it in those kind of contexts too. Thanks | everyone this has really clicked in to place for me :) | drdec wrote: | Not a file path specifically and not an input exactly but I | think the proper word would be an argument. | tremon wrote: | And then we have startx, which starts both an X server and | the X client specified: startx | /path/to/client --with --client-options and arguments -- | --server-options -go --here | | Here, the double dash is used to separate the client options | from the server options (the path to the server binary is | compiled-in, IIRC). | wruza wrote: | It means "stop processing arguments as options and leave them | alone" to getopt-likes. E.g. to rm file named "-f": | rm -- -f | | Idk the word, just minus minus. | soupshield wrote: | > E.g. to rm file named "-f": | | I've defintely had this sort of problem in the past :) | vultour wrote: | rm ./-f | kelthuzad wrote: | I found the "Missing Semester" lectures on YouTube to be pretty | helpful: | | Regarding git there is: | | Lecture 6: Version Control [0] | | [0] https://youtu.be/2sjqTHE0zok | anderskaseorg wrote: | These days it might be better to teach new users about 'git | switch' and 'git restore' (added in Git 2.23, released | 2019-08-16) rather than the two overloaded meanings of the | confusing 'git checkout' command. | | https://git-scm.com/docs/git-switch | | https://git-scm.com/docs/git-restore | ajross wrote: | My feeling is that new users shouldn't be taught about branches | in their local repo at all. Typical cloud-based | git{hub,lab}/gerrit/etc.. workflows generally store all | branches worth talking about on remote systems anyway. | | I find I don't ever bother with managing local branches for | anything in my own workflows. I just git-reset --hard to bounce | between fetched copies of upstream branches as needed. Stuff I | need to work on for more than a few commits in an afternoon | gets pushed to a remote branch regularly anyway as part of | general safe development hygiene. | chasil wrote: | My developers use CVS. | | Sometimes, they are really stupid, and they will checkin | passwords. | | With the RCS archives, I can use vi (or nano, or any other | reasonable editor), and remove this foolishness. | | When I run "git cvsconvert" any foolishness is _ENGRAVED IN | STONE_. | | Removal is possible in git, but not easy. | | This is my problem. THERE ARE SO MANY IDIOTS. What can I do? | | EDIT: For Windows-centric users of git, you need to run this in | every and all repositories RIGHT NOW. | | git grep -i password $(git rev-list --all) | | [actually, everybody should try it] | AnonCoward42 wrote: | I might be an idiot myself, but would `git rebase -i | <commitBeforeSnafu>` do the trick? | | edit: This is interactive rebase, where you can rewrite | history. Instructions are in the file you are editing once | the command is executed. As a rule of thumb, don't rebase on | production, however with such a SNAFU you probably need to. | gizmo686 wrote: | No. The old commits still exist, a rebase just makes it so | that they are not part of the history of the current | branch. If you know the commit hash of a commit containing | the offending data, you can still check it out. You can | also find such commits in the reflog, or if they are part | of the history of any other branch or tag. The data is also | in git's internal data structures if you know enough to | interpret those directly. | | Still, a rebase is a critical part of fixing this. If you | rebase every branch that has the offending data in their | history, and recreate any tags that have the data, then the | offending data would be present only in unreachable objects | (which can still be found through the reflog or knowing a | commit hash). Eventually, git's garbage collection will | clean up such unreachable data. You can force this | behaviour earlier by using the `git gc` command. By default | git will not remove recent objects (which is why you can | reflog your way out of a botched rebase), but you can | override this behaviour as well. | | Of course, all of the above assumes you are working on your | own repository. Given git's decentralized design, you need | to clean up and garbage collect on every clone that did a | fetch since the offending data was checked it. Worse, each | clone also keeps track of remote branches, and considers | those to be reachable as well, so a garbage collection will | not work correctly until a given clone fetches from all of | its remotes after those remotes removed the offending data | [0]. | | Further, there is not good tooling to check that you | actually did this correctly, so when you are done, you need | to hope you fully purged the data. | | The plus side of all of this is that once something is | checked in, it is extremely difficult to accidently delete | it. The downside is that it is also difficult to | deliberately delete it. Also, it is fairly easy to make it | difficult enough to find to negate the day to day benifets | of it still existing, which does very little to protect | against a motivated attacker. | | [0] Fourtuantly, you do not need all of the remote to have | garbage collected, so you could have every make the data | unreachable, fetch on all remotes, then garbage collect. | ramadis wrote: | Chill? | chasil wrote: | What is really far more critical to understand is that my | vi changes what everybody sees in CVS. | | If there is some foolishness, git propagates it EVERYWHERE. | | Every git repository is equal. I have no control of | proliferation. | | Sigh. | alvarlagerlof wrote: | It's more useful to fix the problem before it happens. | Try to set up systems or workflows that make it easy to | do the right thing, rather than trying to fix it | afterwards. | pluijzer wrote: | You can try and talk to your developers with more respect. | People make mistakes and don't have to be idiots or stupid | for it. | | edit: mistakes happen always it is better to change the | workflow in such a way that a the consequences can be | contained. | chasil wrote: | They quit far too much for any rapport. | | I have to walk them through configuring an ssh agent | (usually devolving to pageant.exe) and they are gone in | three months. | | Kind of a big ask. | | EDIT: I do love my job. People? Uh... | paraknight wrote: | "If everywhere you go smells like shit, maybe it's time | to check your own shoes" | electrondood wrote: | > They quit far too much for any rapport. | | The developers you publicly describe as stupid and idiots | seem to leave every three months. Huh. | orf wrote: | Fix whatever processes, tooling, culture or training _you_ | have that leads _your_ developers to make these mistakes | sxg wrote: | Multiple people committing the same mistake is much more | likely to be a systems problem rather than an individual | developer's problem. | | The other reply comments are saying the same thing, but your | (parent) comment needs to be called out. | [deleted] | lstamour wrote: | Stop using any passwords that get checked in. Set expiry | dates for access tokens. Set up git commit hooks that scan | for password or API key prefixes and block the commit. Set up | appropriate .gitignore files, you can place them in | subfolders to keep them simple. | | If possible, switch from using passwords or tokens without | expiry to using ephemeral or time-limited tokens such as | machine or pod identities, JWT tokens, IAM service accounts, | public/private key pairs (if you can get by with only a | public key in the repo) or two-factor authentication. | Consider distributing time-limited passwords with Hashicorp | Vault. | | Some teams might use a cloud-hosted secrets manager or | password manager like 1password to distribute passwords and | then have code load the password as it runs on a developer | machine. GitHub has a secrets scanner, if you pay them enough | money for "Advanced Security" such that secrets can never be | pushed upstream if recognized as such. | | Also, converting from any repo format to another repo format | requires care and multiple repeated attempts. A lot can go | wrong. Reposurgeon (from a sibling comment) is highly | recommended but also not easy to use. It takes a lot of | attention to detail to really get the details right. | User23 wrote: | Git filter-branch will erase your shame. But as others have | said, those credentials are burnt and need to be treated | accordingly. | CrazyPyroLinux wrote: | These days https://github.com/newren/git-filter-repo is | superior. | chasil wrote: | Just kill me now. | | We had the same problem in TFS. | | I found them, I warned them, my riot got us kicked off our | shared server. | | We migrated to our corporate TFS cloud, and they kicked us | off for precisely the same reason. | | This just won't/can't stop. | tigerlily wrote: | Don't use cvsconvert. Use reposurgeon, you will get much more | fine grained control. | | Here's a brief precis on getting started: https://gist.github | .com/ryfactor/f70529438f254d44c0077176508... | chasil wrote: | I don't think that we will move, and I likely will not | assume TFS, but I will look. | garyrob wrote: | I'll look into that, thanks! | garyrob wrote: | I'm going to think about this more. Ironically, I'm in a | situation for a few days where I can't really focus on | technology. | | It sounds like switch and/or restore are probably stable enough | that they could be used instead of checkout for the specific | tasks I'm trying to do in the blog post, so yet another update | will be warranted when I get a chance! | | It's completely usable as-is, so I hope no one is scared off by | thinking it should incorporate switch and/or restore. It's | usable now, and if you do feel like saving a link to it for | future reference, I expect that there will be another way in | the future to do a couple of the tasks using the more modern | syntax. | malkia wrote: | First of all, I'm long time going git n00b (still mainly p4, | and g4 for a bit user), but welcome any hints to easy going | with git (have to use it occassionally). | | Saw this though for switch/restore: | | "THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE." | ilyagr wrote: | I, personally, learned to use git a couple of years ago, have | never learned to use the `checkout` command, and had no need | for it. The goal of `switch`/`restore` is to do everything | that `checkout` does while being less of a confusing mess. | | See also the reddit thread linked by a nephew comment. | garyrob wrote: | Hmm, maybe I should leave as-is, for the time being, anyway! | Thank you! | | Update: based on other comments, I WILL seriously look into | replacing the use of checkout. It sounds like these newer | features are probably stable enough for the simple things | that are being done in the blog post, and that updating the | post will more it a bit more useful as a starting point for | learning git. | | I'm thinking of posting the modern syntax as an alternative | rather than a replacement to checkout, but I have yet to | investigate how stable things are now... will do when I have | time. | | But meanwhile, the checkout method is fine, it works, and | it's well-established for many years. | NoahKAndrews wrote: | I think this Reddit comment has the right idea, especially | now that those commands have been released for 3 years: htt | ps://www.reddit.com/r/git/comments/ifkbfz/comment/g2on6yo.. | . | malkia wrote: | Thank you, and that's a good advice from the comment: | | "So if you're writing a script that needs to work with | dozens of past and future Git versions, use git checkout. | If you need to teach humans how to talk to Git, use git | switch. Some details of some flags may change in the | future, but I'd argue that that'll be a smaller mental | challenge than trying to teach which parts of git | checkout do what." | | I'll try to use more switch/restore | | I've actually used "git stash" more than it should be | (I'm probably applying real bad "p4/g4/svn" like ideas in | my head to the development. As soon as I go into project | with few more people, and I'm lost, though I was able to | make few PR's in github for things - but everytime had to | le-learn the process). | ziml77 wrote: | I sometimes use git stash as a safer alternative to git | reset --hard HEAD. git stash -> check that the state | you've reverted to is actually what you want -> git stash | drop. And since internally stash is just creating a | commit, it's even possible to recover the changes if they | haven't been garbage collected. | noSyncCloud wrote: | Only used Git and SVN before, sorry for noob question. I | guess p4 is Perforce, but what is g4? | wizofaus wrote: | I only found out about git switch recently - super handy when | you want to checkout another dev's branch that isn't tracked | locally yet. There's a case to be made for reserving 'checkout' | for when you specify a filespec rather than a branch. ___________________________________________________________________ (page generated 2022-08-06 23:00 UTC)