[HN Gopher] Confusing Git Terminology ___________________________________________________________________ Confusing Git Terminology Author : soheilpro Score : 367 points Date : 2023-11-02 13:05 UTC (9 hours ago) (HTM) web link (jvns.ca) (TXT) w3m dump (jvns.ca) | asicsp wrote: | See also: Why Git Is Hard | (https://roadrunnertwice.dreamwidth.org/596185.html) | | Discussion: https://news.ycombinator.com/item?id=37799082 | happytoexplain wrote: | Regarding "Why Git is Hard", | | I love Git, but with the huge caveat that it is relative love - | relative to the universe of garbage software trying to perform | complex tasks. I think it has a few glaring issues (the reset | command and the overloaded pages of the official docs come to | mind), but I also think 80% of the criticism aimed at the | design or CLI of Git is undeserved or misapplied. E.g., here's | my quick critique of some of the points under the "alien mental | model" part: | | _> A commit is its entire worldline_ | | _> Commit content is both a snapshot and a patch_ | | _> Branches aren 't quite branches, they're more like little | bookmark go-karts_ | | These are three versions of the same fallacy - technically | correct, but only in the same sense that a text file is "both | text and ones-and-zeroes", or "not text, but actually ones-and- | zeroes". The author is pointing at different abstraction | layers, some of which aren't even necessary parts of the user | mental model. If you don't yet understand concepts like | "abstraction layers" or "implementation details" (e.g. the | difference between "a branch is a series of commits" and "a | branch is represented by a pointer to a commit, which, by the | definition of a tree, resolves deterministically to a series of | commits"), then you will have this problem with any software | that gives you power to work on a complex problem like version | control. | | _> Merge conflicts are actually just difficult_ | | If your version control system makes merge conflicts easy/rare | in the absolute sense, then it is doing dangerous/cute "idiot- | proofing" that will bite you at some point. | | In summary, I think a good chunk of complaints about Git are | actually just complaints about version control (i.e. Git is | hard because version control is hard), or unnecessary | combinations of different abstraction layers (which, to be | fair, most software/documentation hides better from the user, | but IMHO that is a bad thing). Git is an amazing piece of | software ( _relatively speaking_ ). | jcranmer wrote: | Don't worry, git manpages have a builtin glossary, just type in | `git help glossary`, and you can get helpful definitions for | confusing terms: | | > index | | > A collection of files with stat information, whose contents are | stored as objects. The index is a stored version of your working | tree. Truth be told, it can also contain a second, and even a | third version of a working tree, which are used when merging. | | Correction: you can get _unhelpful_ definitions of all the | confusing terminology. | otikik wrote: | You have described my experience with man pages, and in general | with developer-written documentation. I think part of it is | simply that a lot of devs struggle to communicate what they | know to people who don't already know what they know. I also | suspect lack of interest is a big reason (writing the code is | fun, writing the docs is boring). | jgalar wrote: | In my experience, having to explain a software's design in | plain English often reveals that some aspects were poorly | thought-out in the first place. | hinkley wrote: | ...which in turn triggers defensiveness in some people, | making a bad situation worse. | sodapopcan wrote: | A lot of the time the language in man pages fine, but it | could be easily clarified for first-time readers with simple | examples. What is it with that? It seems to be an unwritten | rule that Man Pages Shalt Not Provide Examples. Is there a | good reason for this is or is it a "secret club"-type thing | or something else? | | EDIT: I "let me google that for you"'d myself and found this | [0] right away which explains it, I guess. | | [0] https://unix.stackexchange.com/questions/306189/why-dont- | man... | psunavy03 wrote: | https://www.mountaingoatsoftware.com/blog/the-difference- | bet... | dspillett wrote: | The trouble with a lot of technical documentation, | particularly man-pages and in-tool command-line help, is that | it usually seems written as a reference/reminder for people | who know more-or-less what they are doing already. You can | often work things out from a more standing start, but that | sort of documentation isn't optimised for this so you have to | work for your illucidation. | vbezhenar wrote: | For popular technologies there are often books, tutorials | and other introductory articles. Git certainly has enough | information to start out without reading every manpage. | hiAndrewQuinn wrote: | I think this is why `tldr` is so helpful as a starting point: | It's crowdsourced from other people than the dev who need to | just _get things done_. | shadowgovt wrote: | The single biggest contribution StackOverflow made to | documentation as a whole was to flip the script. | | Instead of the original developer of the material trying to | prognosticate what questions people would have, people | asked questions and either other users or the developer | could answer them. | jaynetics wrote: | As this might not be obvious to all, tldr is a crowdsourced | man-page replacement, and also really useful when working | with git. $ tldr git cherry-pick | Apply the changes introduced by existing commits to the | current branch. To apply changes to another branch, | first use `git checkout` to switch to the desired branch. | More information: <https://git-scm.com/docs/git-cherry- | pick>. - Apply a commit to the current | branch: git cherry-pick commit | - Apply a range of commits to the current branch (see also | `git rebase --onto`): git cherry-pick | start_commit~..end_commit - Apply multiple | (non-sequential) commits to the current branch: | git cherry-pick commit_1 commit_2 - Add | the changes of a commit to the working directory, without | creating a commit: git cherry-pick -n commit | maw wrote: | Believe it or not, I enjoy writing documentation. | | I imagine it as a competition between myself and an adversary | with an uncooperative attitude, one who's prepared to act | smarter, dumber, better informed and more ignorant than I am | in order to to find gaps, inaccuracies, or ambiguities in the | docs I write. | | It doesn't hurt that it improves my understanding of whatever | it is that I'm documenting -- and where it could be improved. | mbork_pl wrote: | This. I also like writing, but I _love_ your description of | technical writing as a (sort of) competition. Thanks! | Tao3300 wrote: | I write docs with my most terrifyingly dangerous adversary | in mind: Future Me. His forgetfulness and capacity for | ignorant destruction are unparalleled, at least that's what | Past Me says. | kagakuninja wrote: | In the '80s, all we had on UNIX were man pages, and I was | able to glean useful info from them. | | Now they make my eyes glaze over, probably because every | command now has 57 options. I just google how to do the | thing. | dboreham wrote: | There have never been "just man pages" in Unix. E.g. V7 had | a number of papers (in troff format which could be rendered | to the terminal or sent to the printer in finite time) that | helped with understanding how to use the system (assuming | you had more than the bare minimum disk space on your | machine). | nvy wrote: | I basically never read man pages. In the overwhelming | majority of cases you spend 20+ minutes reading the manual | and it ends up not answering your question (or at least this | is my experience) so you end up just doing a web search | anyway. | bjornasm wrote: | Same here. I feel like a majority of documentation and | eapecially man pages are helpfull if you already know it, but | just need a reminder. | PH95VuimJjqBqy wrote: | That hasn't been my experience at all, I find man and info | pages hugely helpful. | masto wrote: | A lot of documentation is atrocious, particularly for newer | stuff. But I kind of disagree on man pages. At least, when I | first encountered Unix, it was on old SunOS machines, and I | remember being impressed first that everything _was_ | documented, and second, that the documentation was | comprehensive and useful. | | The things that make me most frustrated are when docs are | missing, incomplete, or useless ("--foo: enables the foo | option"). When it comes to man pages, at least in the good | old days, I felt like I could always rely on them to cover | all of the possible inputs, outputs, and errors, and to | describe them, if not in the plainest language, in a way I | could understand without being the author of the program. | | For example, I don't have much bad to say about | https://shrubbery.net/solaris9ab/SUNWaman/hman1/ls.1.html | hinkley wrote: | "I understood every one of those words." | jakub_g wrote: | The upside of this is, when I have a bad humour, I go to git- | man-page-generator, and one minute later I'm laughing my arse | off. | | https://git-man-page-generator.lokaltog.net/ | esoterae wrote: | The way in which the author structured the language used to | describe things may be the most confusing thing of all. For | example: | | "HEAD^ and HEAD~ are the same thing (1 commit ago)" | | Followed by: | | "But I guess they also wanted a way to refer to "3 commits ago", | so HEAD^3 is the third parent of the current commit, and HEAD~3 | is the parent's parent's parent." | | The author's language implies a contradiction they immediately | prior said doesn't exist. If these two distinct constructs were | indeed different ways to define the same relationship, the second | paragraph would say "^3 and ~3 are both ways of saying the third | parent of the current commit, or the parent's parent's parent." | Instead, they've defined the constructs as different once again. | jcranmer wrote: | > If these two distinct constructs were indeed different ways | to define the same relationship, the second paragraph would say | "^3 and ~3 are both ways of saying the third parent of the | current commit, or the parent's parent's parent." | | They're not the same thing. Merge commits can have multiple | parents, and HEAD^3 refers to the third parent. If HEAD is not | a merge commit, then HEAD^3 doesn't refer to anything. HEAD~3, | by contrast, refers to following the parent's parent's parent, | independent of how many parents any of the commits in question | had. | dicytea wrote: | > HEAD~3, by contrast, refers to following the parent's | parent's parent, | | More specifically, following _the first_ parent only. _man | git-rev-parse_ (surprisingly) has a nice explanation: | | > A suffix ~<n> to a revision parameter means the commit | object that is the <n>th generation ancestor of the named | commit object, following only the first parents. I.e. <rev>~3 | is equivalent to <rev>^^^ which is equivalent to <rev>^1^1^1. | ahmedfromtunis wrote: | To make it even clearer, "^3" is when a team of, say, 4 | commits contributed to the current commit. "^3" is then the | team member number 3. | | "~3" however refres to grand-grand-parent to the current | commit. | | It's confusing because ^ looks like an up-arrow, so we think | of it as a pointer to look n levels up. That's not the case. | j16sdiz wrote: | I think the author got "heads" wrong and failed to explain how | heads and branches are different concept with the same | identifier. | wavemode wrote: | Care to explain? | pickledish wrote: | I guess I've never really found the "ours" and "theirs" | terminology too confusing -- it's called "ours" because that | refers to the branch I have checked out right now (i.e. that's | "my" branch), and "theirs" because that's the other branch, the | foreign one which isn't currently "mine". | | But maybe that's because I almost never use rebase, where it | apparently is switched? | sakisv wrote: | Ah, but it's not switched! Remember that rebase essentially | replays commits against a different branch/base commit: | | e.g. if you have your branch `feature-1` and want to rebase it | on `main`, then you would do `git checkout feature-1; git | rebase -i main` | | Git will then switch to main (that's "ours" now) and then it | will replay the changes from `feature-1` on top of it (that's | "theirs" now) - like cherry-picking all your commits, but in | sequence (and not actually merging them in `main`) | saghm wrote: | > Remember that rebase essentially replays commits against a | different branch/base commit | | This is exactly the reason that git is hard. Its abstractions | are so leaky that you'd think it's interface is designed to | be a sieve. I really like the underlying model git uses, but | the actual CLI does a terrible job of providing mechanisms to | use it to the point where you have to pay far too much | attention to the internal model to be able to avoid footguns. | It's an indictment of a poor API when the best way to figure | out how to do something isn't to search the docs but to | figure out how to express the thing you want to do as an | operation on the underlying model and then Google that to | find the invocation that happens to map to that operation | (and half the time, it's not even it's own subcommand; it's | just some obscure flag to a grossly overloaded subcommand | like `checkout`). | porridgeraisin wrote: | I can't quite find it, but there's a video on git | internals, and how you can make commits without using the | git cli, by directly manipulating .git folder. That really | helped me deal with certain idiosyncracies of the git cli | (either I guess a hacked-together sequence of git cli | commands, or i know what to nuke) | technojamin wrote: | That's exactly why the author included it. Your definition | seems appropriate at first and is probably what most people | assume: "ours" refers to "my current branch" (HEAD), and | "theirs" refers to "the other branch". | | This breaks down during rebase, where the terminology gets | reversed. The definitions are more accurately: | | - "Ours" refers to "the branch whose HEAD will be the 1st | parent of the merge commit" (during merge) or "the branch who | will get commits applied on top of its HEAD" (during rebase) | | - "Theirs" refers to "the branch whose HEAD will be the 2nd | parent of the merge commit" (during merge) or "the branch whose | commits will be applied on top of the other branch" (during | rebase) | | This gets a little more complicated during "octopus merges", | where there are multiple "theirs" branches. | hotnfresh wrote: | I'm constantly having to double-check directionality for pretty | much everything in Git. I find none of the terminology or | ordering intuitive, and never trust myself to have remembered | it correctly. Ditto whether various commands that take or imply | ranges are inclusive or exclusive. | petepete wrote: | git has had `switch` and `restore` for years now, they provide a | more sensible interface than having `checkout` do so much. | chungy wrote: | I honestly never wrapped my head around the `git branch` and | `git switch` commands and continue to use checkout for | everything branch-related because it's what I've been doing | since 2007. I haven't given them a fair shake, granted, but to | me it's kind of like complaining that Unix's mv is confusing | because it also renames files. | | `git restore` though is slightly nicer than using checkout. | I've incorporated its use into my workflow, even though I've | previously used checkout for the same operation. | petepete wrote: | I've also been using git since around that time but had no | problem _switching_ in 2019 because I'd also spent many years | using svn. Choice is good, switch just fits my brain better. | civopsec wrote: | See also: | | - The git staging area, the term literally everyone agrees with | | - https://news.ycombinator.com/item?id=28143078 | | > "Your branch is up to date with 'origin/main'" | | > ... But it's actually a little misleading. You might think that | this means that your main branch is up to date. It doesn't. | | No need to well-actually this one. Isn't the Two Generals problem | applicable here? If you are being really pedantic, it is | impossible to tell whether you are "up to date" right this split | second. Even if you do a fetch before `status`. So what's the | reasonable expectation? That the ref in your object database--on | your own computer--is up-to-date with some other way-over-there | ref in an object database last time you checked. | | A simple `status` invocation can't (1) do a network fetch | (annoying) and (2) remind you about the fundamentals of the tool | that you are working with. In my opinion. But amazingly there are | a ton of [votes on] comments on a StackOverflow answer[1] that | suggest that those two are exactly what is needed. | | > I think git could theoretically give you a more accurate | message like "is up to date with the origin's main as of your | last fetch 5 days ago" | | But this is more reasonable since it just reminds you how long | ago it was that you fetched. | | [1] https://stackoverflow.com/questions/27828404/why-does-git- | st... | | ... | | Another thing: I thought that `ORIG_HEAD` was related to | `FETCH_HEAD`, i.e. something to do with "head of origin". But no. | That "pseudoref" has something to do with being a save-point | before you do a more involved rewrite like a rebase. Which was | implemented before we got the reflog. I guess it means "original | head"? | dooglius wrote: | The expectation is that the information you get is up-to-date | as of the time you started the status command, yes there can be | a race in the time it takes to present information to your | terminal but that's a small time window. This more or less | means you want to fetch, yes. Two Generals problem is only | applicable on the remote side, which may keep sending | retransmits for a while, if it doesn't get acks that you | received its data (which isn't the client's problem). If the | client doesn't get data from the server presumably the right | behavior (which I'd expect happens now with fetch) is to hang | and print an error after a timeout. | civopsec wrote: | > The expectation is that the information you get is up-to- | date as of the time you started the status command, | | Why is that the expectation of a "distributed VCS"? | happytoexplain wrote: | It is not - it is the expectation of the phrase "up to | date". You don't have to alter reality, you can just alter | the description of reality to be a little more | conversationally precise. | fragmede wrote: | That's _your_ expectation, but how does that work without | Internet access? You 're holding it wrong... | happytoexplain wrote: | It's pretty presumptuous to just tell somebody what they | think about English is wrong. We can change the wording | without changing the system (Though technically we could | even alter the system to update the remote ref as part of | the status command, and the wording would be much better to | a human! Though we shouldn't, since, as you imply, we don't | want the status command to be dependent on a network call.) | | Edit: Removed accusation of "Conflating the implementation | of the system with the wording of its output". | happytoexplain wrote: | I'm pretty pro-Git, but I agree with the author on the wording | of that message (though I disagree with their suggested | alternative). "Your branch is up to date with 'origin/main'" is | technically correct, but the usage of the phrase "up to date" | implies on a casual reading _two_ things: That main matches | origin /main, and that origin/main is up to date (i.e. that it | was updated as part of the command, or is being kept up to date | automatically and the last successful sync was arbitrarily | recently). We're talking about a user-facing status message, | not a machine-readable signal that must be true during this CPU | cycle. This is a reasonable interpretation without having to | get into networking theory. | | "Up to date" means caught up in time, as opposed to space. | Local branch positions are more like space ("where is this | branch pointing?") and remote ref state is more like time | ("when did I last update the remote ref?"). I know, that's very | subjective. Either can mean either. | | Anyway, I think a better wording might be "Your branch matches | origin/main" or "Your branch's head is the same as origin/main" | or "Your branch is pointing to the same commit as origin/main" | or some other tradeoff between verbosity and clarity. Maybe | with the author's suggestion as a parenthetical: "Your branch | ... origin/main (remote ref last updated 5 days ago)." | civopsec wrote: | > Anyway, I think a better wording might be "Your branch | matches origin/main" | | That's fine. And also less partial to the implicit view that | the remote ref is the thing you are supposed to be "up to | date" with. | Lutger wrote: | I like the last one and would shorter it to: | | "Your branch ... origin/main, updated 5 days ago." | fernandotakai wrote: | >A simple `status` invocation can't (1) do a network fetch | (annoying) | | i don't think that's annoying. i want network operations to be | explicit, not implicit. when i do git status, i wanna know the | status of my repository as is in my file system. | | if i want to know what's going on in another remote, i will | fetch that and then compare. | javier_e06 wrote: | Not to pile on but also the idiots at Bitbucket cooking the "pull | request" term. A "pull" is the action of merging remote changes | into a local repo. What the user is actually requesting is for | the server to merge her/his remote changes into a branch. Gitlab | calls it a "merge request" which is right. I saw someone doing a | fetch and their commits disappeared! They where hidden because | the repo went backwards in time. Git hides all those tidbits of | information in the status but if you don't use git-prompt or | powerline-shell ...you are working in the dark. | civopsec wrote: | Github popularized "pull request" and I think it's a fine term. | Whether you are "actually" pulling from a different repository | instead of just doing a "merge request" (idiosyncratic GitLab | term) within the same repository doesn't feel like an | interesting distinction. | fragmede wrote: | If you're treating git as a centralized VCS, that is, there | is only a singular upstream, perhaps, say, GitHub.com, then | that makes sense. That, however, is not the only way to use | the tool (though GitHub.com obviously has their own opinions | on whether that should be the case or not), but the upstream | repository that you're pulling from certainly it's an | important distinction if you're using the tool beyond how | GitHub.com wants you to. | civopsec wrote: | So you should change your terminology depending on some | "how X" your workflow is? If you are working with two | repositories between yourself and a teammate then it | becomes "pull request", but then if you move back to the | centralized company upstream then you're doing "merge | requests"? The distinction is not interesting enough to, | well, make a distinction over. | | > That, however, is not the only way to use the tool | | And "pull request" somehow is exclusionary? No, because you | can use it to talk about both inter- and intra-repository | changes. | lemoncucumber wrote: | Yeah, `git pull` is just shorthand for `git fetch` | followed by `git merge`, so it's technically a superset | of a "merge request". | | And it also handles the cross-repo case, which is a | common case in the Github model of "make your own | personal fork of the upstream repo and send PRs from | there," which has advantages -- it allows random people | to send PRs without needing to give them permission to | e.g. pollute the upstream repo's branch namespace. | bjornasm wrote: | Disagree. Why are you both pulling when you want code from | the repo and when you want to put your code up to someone | elses repo? | Ajedi32 wrote: | You pull when you want code from their repo, they pull when | they want code from your repo. You don't have permission to | push to their repo, so instead you _request_ that they | _pull_ from yours. | thomastjeffery wrote: | From the server's perspective, you are the remote and it is | local. You are requesting that the server pulls from you. | | ...at least, that's how I always read it. | dboreham wrote: | I thought it originated in a decentralized git use case where | developer A asks developer B to pull their proposed new code | into their (local) repo. So predating server hosted git. | Perhaps I made that up though. | thomastjeffery wrote: | That's generally my point: despite the server _presenting | itself as_ a centralized "hub", it is really just another | decentralized user of a decentralized git repo. | | From a git perspective, there is no meaningful difference | between server and client. | jordigh wrote: | The original idea, as enshrined in git-request-pull(1), was | that we would all have our own git repos somewhere, | kernel.org/git or redhat.com/git, and then we would request to | pull from each other by sending emails to each other to pull | from each other repos across different servers, even different | organisations and different domains. | | Github took inspiration from git's request-pull command but | instead reinterpreted it as merging from one github repo to | another. | bjornasm wrote: | This is the one that allwaays was impossible for me to wrap my | head around. Surely it is a push or merge request not a pull | request. | PH95VuimJjqBqy wrote: | It's a request for the other person to pull, it's only a push | if the requestor is doing the action (and they're not). | ajross wrote: | So... technically no. It really is a "pull" request from | Github's perspective. A PR is (1) a bunch of | review/comment/history/hook tracking in the web/cloud | backends and (2) a single git branch name somewhere else on | github, writable by the author, which contains the changes. | | The underlying action of merging a "pull request" is to pull | from the submitted branch to the target branch. It's no | different than Linus doing it from a maintainer branch. | ptx wrote: | The Git book [0] explains where this term comes from and how it | makes sense. | | In short, it's not a request to a server but to another person. | You're requesting that they pull your branch to take a look at | the changes you want to contribute to the project. | | [0] https://git-scm.com/book/en/v2/Distributed-Git- | Contributing-... | MzHN wrote: | One of my favorites: | | You want to permanently destroy all work you've done since last | commit (maybe it was a bad start and you want a fresh one). | | The (new-ish) command you run is git restore . | drewolbrich wrote: | This makes sense though, because in Swedish, the words for | restore and destroy are homonyms. | hyperhopper wrote: | See also: Git Koans | | https://stevelosh.com/blog/2013/04/git-koans/ | sakisv wrote: | I was having a similar hard time to remember most of these (the | remaining ones I just don't use often, so I still haven't quite | grasped). | | The single thing that made everything "click" together is that | most things are just pointers to commits: branch names, HEAD, | tags, all of them are pointers. | | HEAD is pointing to the commit you're currently looking at | | The name of each branch (e.g. `my-feature` points to the latest | commit of that branch) | | When you're on main and you `git checkout -b my-feature` then you | have at least 3 pointers to the latest commit on main: `main`, | `my-feature` and `HEAD`. | | Every time that you make a commit on `my-branch`, then both the | `HEAD` and `my-branch` move to point to the new commit. | | "detached HEAD" means that the the `HEAD` (the commit you're | looking at) is not pointed at by a branch. | | The difference between tags and branches is that the tags point | to a specific commit and do not move. | | ---- | | The other thing caught me out multiple times is that most | commands seem inconsistent because git assumes default arguments: | | `git checkout file.txt` is the same as `git checkout HEAD -- | file.txt` | | When you're on `my-branch`, `git rebase main` is the same as `git | rebase main my-branch` | | The difference is that the latter you can run it from other | branches too. | | ---- | | Last but not least, when everything goes wrong, the single | command that can take you out of any weird situation is `git | reflog` which shows you all the commits that HEAD has pointed to. | | Having said all that, I'm glad that git is acknowledging all this | confusion and are implementing commands with fewer surprises and | simpler interface as that will make it easier for newcomers to | pick it up. | bingemaker wrote: | One thing that has really helped me understand git better is | DAG (https://en.wikipedia.org/wiki/Directed_acyclic_graph). | Whenever I do `git add <file/folder>`, it is somewhat easier to | imagine how new blobs are created and how they are linked. | | For beginners it is a fun exercise to understand why empty | folders can't be added to git. | bonzini wrote: | Not that there is any reason why git _has_ to forbid the | existence of empty tree objects. | | (Fun fact, all such empty trees would be deduplicated to a | single object). | strifey wrote: | I love this explanation. One unfortunately confusing extra | piece that some people might occasionally run into is that | there are two types of tag. Most tags are what you describe: | pointers (git ref) to a commit (git object) and nothing more. | These are usually referred to as lightweight tags. | | There are also annotated tags that can contain a message, have | a timestamp, and sha, etc. These are proper git objects that | behave a lot like commit objects, except they're still | typically only referring to another git object (commit). | recursive wrote: | I thought I understood tags... | | But now what's a "proper git object"? Is there an improper | git object? Is there a proper git non-object? | oasisaimlessly wrote: | "proper git object" = anything that has its own unique | hash. | derefr wrote: | Underneath the SCM plumbing, the "true core" of git is a | content-addressable object store. (See https://git- | scm.com/book/en/v2/Git-Internals-Git-Objects) | | When you `git fetch`, git is asking the remote to walk a | tree of objects -- starting at the commit object that the | ref points to -- and deliver them to you, to unpack into | your own object store. | | Git _could in theory_ do a lot with just objects -- with | the whole "data state" of the repo (config, reflog, etc) | just being objects, and then one toplevel journal file to | track the hash of the newest versions of these state | objects. (Sort of like how many DBMSes keep much of the | config inside the database.) | | But git mostly isn't designed to do this. Instead, git's | higher SCM layers manage their state directly, outside of | the object store, as files in well-known locations under | .git/. This means that this higher-level state isn't part | of the object-store synchronization step, and there must | instead be a domain-specific synchronization step for each | kind of SCM state metadata where applicable. | | Tags are an interesting exception, though, in that while | the default "lightweight" tags _are_ "high-level SCM | metadata" of the kind that isn't held in the object store; | "annotated" tags _become_ objects held in the object store. | | (To be honest, I'm not sure what the benefit is of having | "lightweight" tags that live outside the object store. To | me, it looks like tags could just _always_ be objects, and | "lightweight" vs "annotated" should just determine the | required fields of the data in the object. Maybe it's a | legacy thing? Maybe third-party tooling parses lightweight | tags out of the .git/ directory directly, and can't "see" | annotated tags?) | bonzini wrote: | Lightweight tags are simply references to commits that | lie in refs/tags instead of refs/heads. Annotated tags | are references to tag objects rather than commit objects. | In both cases, the purpose of the reference is to give | the object (tag or commit) a name. | | I think no one uses lightweight tags anymore, except if | you push by mistake a commit to refs/tags/something. | nvy wrote: | >the single command that can take you out of any weird | situation is `git reflog` which shows you all the commits that | HEAD has pointed to. | | Can you elaborate on why that's helpful? I rarely get into a | weird state with git but when I do it's almost always | faster/easier to just delete the repository, re-clone, and re- | apply my changes manually. | CorrectHorseBat wrote: | When you accidentally delete a local branch or mess up a | rebase you can use the reflog to retrieve your lost commits | olddustytrail wrote: | If you accidentally symlink the wrong file, would you find it | easier to delete the whole directory and restore from backup, | or just learn how to change a symlink? | sakisv wrote: | A recent scenario had to do with me rebasing something to | squash out some intermediate commits, and then I opened a PR, | only to realise that some of the things I squashed I actually | needed them. | | With reflog I was able to go back before my rebase and redo | it again, more carefully this time. (Unfortunately I couldn't | just cherry-pick the thing I wanted) | | In general it saves you from having to do what you described | with delete/re-clone/re-apply things. | afiori wrote: | I believe that detached HEAD means that there is not a current | branch, that is no branch will be updated the next time you | commit. | | You can get to detached HEAD even if the commit is pointed to | by a branch | derefr wrote: | > pointers to commits | | Or to use the name git gives to that concept, "refs." Thus | _reflog_ :) | | Also, one thing that I've found hasn't occurred to most people | using git, is that all the branch/tag/etc refs of your fetched | remotes, are _also_ refs, able to be referenced anywhere you | can name a ref. | | For example, if you ever want to say "I don't care what's on | this branch, don't fast-forward _or_ merge _or_ rebase, just | overwrite my local branch with what 's on the remote!" then | that'd be: git checkout foo git reset | --hard origin/foo | sakisv wrote: | Ah yes, the fact that git brings the remote stuff locally | when you `git pull` and all the `origin/<whatever>` are just | branch names is something that I realised only too late. | | As for the refs, yes, good point ;) | xorcist wrote: | When you do 'git fetch'. The 'pull' is just an alias for | fetch + merge (or rebase, depending on local settings). | mjochim wrote: | > Or to use the name git gives to that concept, "refs." Thus | reflog :) | | A command name that I read as re-flog for the longest time | :D. I really wondered about the strange, strange name for | quite a while before I bothered to look up what it does and | found out that I should read it as ref-log and that it is, | indeed, a very useful thing. | virtue3 wrote: | Really great point and also really illustrates the tree | structure underneath the hood for git and how it rules | everything. | | The joke that isn't a joke is that you really need a CS degree | to use git. It's not wrong. | | The git default arguments makes for a very inconsistent | experience, agreed. | | And then `git checkout .` vs `git reset --hard/soft` vs `git | cleanup` are all super similar but very different. | | Still love it more than perforce/svn (I did like mercurial a | little better back in the day but I doubt that might still be | the case). | | ----- `git reflog` is king and shows you the truth. | sleepybrett wrote: | Yeah anyone I run into that 'doesn't get git' and only has | like the four commands they ever run... I point them at | https://git-scm.com/book/en/v2/Git-Internals-Git-Objects | | Once you internalize that git unlocks. | cloudwalk9 wrote: | I use Stable Diffusion (A1111 webui) and sometimes run into | config issues, sometimes untracked by git. Nothing more | catastrophic than doing `git clean -dfx` by habit from | tinkering with Debian packages and knowing that command | actually resets everything that `git reset --hard` doesn't... | | And then accidentally wiping out all of your checkpoints and | generated images :') | sampo wrote: | > HEAD is pointing to the commit you're currently looking at | | HEAD pointer is pointing to the branch pointer (e.g. my-branch) | which is pointing to the commit. (Except in a detached HEAD | state.) | | > Every time that you make a commit on `my-branch`, then both | the `HEAD` and `my-branch` move to point to the new commit. | | HEAD pointer keeps pointing at the my-branch pointer, and only | the my-branch pointer moves to point to the new commit. But of | course, when you now follow HEAD to my-branch to the commit, | now you end up to the new commit. | | > "detached HEAD" means that the the `HEAD` (the commit you're | looking at) is not pointed at by a branch. | | "Detached HEAD" means that HEAD is pointing directly to a | commit, instead of pointing to a branch pointer. | | You can have a detached head state, where both HEAD and the | branch pointer point to the latest commit. If you use `git log | --decorate`, for the latest commit it will show (HEAD, my- | branch) instead of the normal (HEAD -> my-branch). | sakisv wrote: | > "Detached HEAD" means that HEAD is pointing directly to a | commit, instead of pointing to a branch pointer. | | Ah, thanks for pointing it out, always good to learn the | finer distinctions | iamcreasy wrote: | > HEAD pointer is pointing to the branch pointer (e.g. my- | branch) which is pointing to the commit. (Except in a | detached HEAD state.) | | Yes! Here[1] is a nice picture about from Git Reset | Demystified article. | | [1] https://git-scm.com/book/en/v2/Git-Tools-Reset- | Demystified | jacobegold wrote: | I think that this video should be considered mandatory viewing | if you're a developer using Git -- the whole lecture starts | from the basic data structures involved and builds from there, | as opposed to the way that it seems many people approach Git: | "What command do I run?" | | https://www.youtube.com/watch?v=2sjqTHE0zok | SAI_Peregrinus wrote: | That's great evidence that git's UI is such a leaky | abstraction that it's actually terrible. | Terr_ wrote: | > Last but not least, when everything goes wrong, the single | command that can take you out of any weird situation is `git | reflog` which shows you all the commits that HEAD has pointed | to. | | And if you're feeling extra-paranoid like me, a `git rev-parse | HEAD` and copying that string down somewhere safe _before_ | embarking on a tricky process with lots of merge-conflicts or | other shuffling. | | It's nice to have confidence that I've accurately identified | _which_ state is the last-known-good one--not one a few steps | too far into the chaos-zone--and that I can usually get back to | if everything goes to hell. (Barring unwise use of stuff like | `git gc` or `git filter-branch`.) | andrewla wrote: | > "can be fast-forwarded" | | I find this one annoying because I generally don't want to run | `git pull` -- I almost never `git pull`, I usually just `git | fetch` and update my branches as necessary. I do wish there was a | built-in shortcut for "try to fast-forward this branch"; I often | just do a rebase or a merge, which will do the right thing for a | fast-forward, but won't fail if a fast-forward is impossible. I | can do `git merge --ff-only`, but I would like it if `git | fastforward` or `git ff` was available instead because for me it | is such a common operation. | | To forestall the obvious -- I don't like to make custom aliases | or commands (though I've done it in the past) because it makes it | harder to migrate between environments. | ericyd wrote: | I don't mean any criticism but I'm genuinely curious: how often | are you migrating between fresh git environments? | ksenzee wrote: | I'm not convinced this matters. It's very important that some | things be kept easy and accessible even if you don't do them | very often. I don't call emergency services very often, but | when I do, it had better be trivially easy. I don't spin up a | new server very often, but when I do, I need to be able to | function there without immediately installing a bunch of | config. I don't help colleagues who need git assistance very | often, but when I do, the last thing I need is to mess | something up for them because all my aliases and defaults are | missing. | Am4TIfIsER0ppos wrote: | git ff | | Very useful to make a git alias for that. When git bitches at | my about the unknown command on the work servers I know I can | just use the full merge command. | mckn1ght wrote: | I have a shell alias for this: gff='git fetch && git pull | --ff-only' | ZeroGravitas wrote: | I believe you can set the default to be --ff-only then you only | need to specify if you want to merge. | | Despite knowing this is an option it's still hard for me to | find decent documentation, but I think this is probably the | best I found: | | https://salferrarello.com/git-warning-pulling-without-specif... | andrewla wrote: | That's even worse because it will just do the wrong thing | when I'm on a different setup. At least with an alias the | system can say "yeah, I ain't never heard of 'ff'" so I can | fall back on a default. | Tomis02 wrote: | It's been about a decade since git "won" the version control war | due to the (yet another) unjustified tech hype wave, and we're | still having difficulties with what should be trivial tasks. I | remember reading a comment by Linus Torvalds being surprised that | people started using git directly rather than putting a | friendlier layer on top. If it was capable of introspection, the | industry would admit it made a mistake by going with git and | switch to another VCS instead, rather than wasting huge amounts | of time on a tool whose only job is to save text. | Lutger wrote: | > whose only job is to save text | | I don't see git as a tool to save text, its for coordinating | changes on the same 'text' by multiple people, and doing so | quite precisely and reliably, _without_ blocking anyone 's path | forward. Try that with word. | | It could be better, yes. But I'm always surprised by the hate | git gets. Its an amazing tool and miles ahead of the tools we | created for non-developers (word, google docs, etc). | | Maybe its because I'm old enough to remember when subversion | was king. | tharkun__ wrote: | This. Git is miles ahead of anything else. | | Is is entirely intuitive to everyone? No. | | Did developers always have trouble with version control and | merging? Yes. | | In my experience most devs don't grok version control, | period. It does not matter if it's SVN, CVS, RCS, Visual | Source Safe, Clearcase, Perforce, you name it. Or now git. | rebolek wrote: | If you think Git is miles ahead of anything else, you | probably haven't really used anything else. | | I don't think that Git sucks, it's usable. But there are | better alternatives. | Tomis02 wrote: | > whose only job is to save text | | It's a hyperbole, a figure of speech used to make a point. | I'm pretty sure everyone on HN knows what git is used for. | | > Maybe its because I'm old enough to remember when | subversion was king. | | I used SVN for more than a year. Why would you compare git | with SVN rather than other DVCS like Mercurial? | Lutger wrote: | > It's a hyperbole, a figure of speech used to make a | point. I'm pretty sure everyone on HN knows what git is | used for. | | I know. The hyperbole makes it sound as if gits job is | actually quite simple and we could easily have a better | system. But I disagree with that, I don't believe it is | simple. Most other tools have and are failing still at | this. | | > Why would you compare it with SVN rather than other DVCS | like Mercurial? | | Because SVN ruled the world back then and that is what I | and many other devs used. Many of us went from SVN to Git | without even knowing what Mercurial was. That explains why | I was (eventually) so in awe of git, had I gone from | Mercurial to Git I might have lamented the loss of a more | friendly system. I do actually remember doing the odd thing | with mercurial and it being much smoother to work with, but | then git was already becoming the dominant player. | Tomis02 wrote: | > Many of us went from SVN to Git without even knowing | what Mercurial was. | | Yeah I know, that's the problem. In other words, many of | us decided git is the best because many of us didn't know | any better. | | But it's been more than a decade, surely that's enough | time to reevaluate one's position. | scottlamb wrote: | > Maybe its because I'm old enough to remember when | subversion was king. | | Heh. I'm old enough to remember when CVS was king. Subversion | was a huge improvement. Git was too. I have every reason to | believe further huge improvements are possible. They might | have to be gargantuan though to overcome inertia by now. | jordigh wrote: | In 2013, it was far from clear that git would win. There was | still a sizable amount of users of darcs, Mercurial, svn, and | even cvs. Many of the tools of that era would have plugins to | support all of them. | | I wish we still had that, because git monoculture also means | that anything that replaces git first has to reimplement git. | This means that just like ASCII or scroll lock buttons, we're | stuck with git mostly forever. | PH95VuimJjqBqy wrote: | > unjustified tech hype wave | | git won for good reasons, it's clearly better than what came | before it. It may be popular to shit on it now (similarly for | jquery), but when it arrived on the scene it was clearly an | improvement. | regularjack wrote: | Git won because it's better than Subversion, and because of | GitHub. | failingslowly wrote: | Hard agree. | | Weekly, I witness co-workers confused about git, I see posts | online asking for help, I see articles like the one here once | again trying in vain to explain something that should be | simple. | | In all my time coding, I don't remember anyone wasting hours | trying to undo some mess they'd made in SVN, TFVC, Perforce, | etc. | | Tools exist to make our lives easier. If they can't do that, | they don't deserve our time. | retpoline__ wrote: | >It's been about a decade since git "won" the version control | war due to the (yet another) unjustified tech hype wave | | Hah, I've recently wrote a post about similar issue - why we | may be locked with git. | | >So what's the issue here? I'm worried that just because GitHub | is so good, then unless they decouple from git as letters | management engine and allow any/other, then we will be locked | with git. | | https://trolololo.xyz/github | | https://news.ycombinator.com/item?id=38098109 | dgan wrote: | "Your branch is up to date with origin/master" is the biggest lie | i am being told on daily basis. I just "pull" every time | abledon wrote: | should be "Your branch is up to date with the local copy of | origin/master, last updated on XXXX-XX-XX:XX:XX:XX" haha | pests wrote: | That sounds like the origin/master branch last got an update | on XXXXXXXXXX, not that you checked out your local copy on | that. I would fetch and then be wondering why nothing | charged. | | Further it does nothing - it tells you nothing about the | remote. It could be 1 second or 100 years and you would still | need to fetch to determine if anything is different. Then | what is the information for? | SAI_Peregrinus wrote: | By the last line's logic there would need to be an atomic | fetch & compare. `git fetch && git status` still has the | same race condition! | jlarcombe wrote: | that's the most common confusion yes! along with 'stage' vs | 'cache' vs 'index'. | Lutger wrote: | Nice. But technically its true. origin/master is not master on | origin. It just refers to the last known commit pointed to by | origin/master, which gets updated when you fetch (pull | automatically fetches). | | ls -l .git/refs/remotes/origin/master | | origin/master is just a file on your system, you can see when | it has been changed. It doesn't magically get updated. Do `git | fetch origin` and if there are any changes, you'll see the | timestamp change, and the contents: | | cat .git/refs/remotes/origin/master | | The basics of git are so simple, you can implement the core | data structures and some operations in a day. It is really | worth it to get to know these. | | Somehow git has managed to create a very complex user interface | on top of quite a simple core. | cush wrote: | > It just refers to the last known commit pointed to by | origin/master | | The confusion lies in that origin refers to different things | depending on if it's `origin master` or `origin/master`. Eg | `git pull origin master` does the thing we expect | Y-bar wrote: | > But technically its true. | | Is it though? | | Consider a bank telling a store I am buying things at "This | person has has EUR450 in their bank account", when at that | moment I have EUR310. The store would be rightfully pissed at | the bank for effectively lying when it is made clear later on | that the transaction could not be completed and the bank | answers "well, the person had EUR450 a few days prior to you | asking us". | | Without an explicit temporal information it is explicitly | now. | | Without an explicit status on sync status it is implicitly | saying sync is up-to-date. | | It's a lie of omission. | fernandotakai wrote: | >It's a lie of omission. | | but it's not? | | if you have an old bank receipt that says you have $450 in | your account, but you actually have $310, you need to "get" | a new receipt that has the newest value. | | you do that by issuing git fetch origin. then you can git | merge origin/master to make everything up-to-date. | Y-bar wrote: | Bank receipts always have a date and time, that's | _exactly_ the point I am making, the omission is part of | the lie. | fernandotakai wrote: | you are getting confused here. | | what you have is a "paper receipt" (your checked out | version) from your bank. something that, if you need an | up-to-date version (from another remote), you need to | request a new one (by issuing git fetch). | | git is, by default, distributed, so whenever you need to | see the world outside, you need to be explicit. linus | made it this way because back in the day (not sure right | now tbf) tons of kernel developers do work without any | internet connection, and would only connect to pull/send | patches. | | this talk[0] by linus from 2007 (i remember watching it | on google videos lol) explains really well where the git | mentality came from. i really recommend it to you, since | it feels like you are not really getting how git works. | | [0]https://www.youtube.com/watch?v=4XpnKHJAok8 | SAI_Peregrinus wrote: | If you have a paper recipt (git status) it tells you when | it was up to date, so you can determine whether you need | a new one. Git doesn't provide that info. That's the | problem, not that it can be outdated, but that it omits | the date/time! | ksenzee wrote: | Very good point. "Up to date with origin/master as of 4 | hours ago" would be an improvement. | pests wrote: | That is a lie though. Who knows if the remote has been | updated? You wouldn't find out about that 4 hours until | you did a fetch. | | You can't go to the hotel desk clerk and ask if you have | any messages. Then for the next four hours keep telling | people "the front desk has no messages for me" despite | you not asking them in the last 4 hours. Things could | change! | ksenzee wrote: | No, this is exactly like a receipt from the ATM. "Your | bank balance is $300.00 as of 10/10/23 10:10." That was | weeks ago, so I know to ignore it. The wording can likely | be improved. Maybe "You are up to date with origin/master | as last fetched 4 hours ago". | pests wrote: | > That was weeks ago, so I know to ignore it. | | But you haven't talked to your bank, used an ATM, or been | on the app in weeks! Your balance could be totally | different - bills have came out, you got paid, interest, | etc. | | You are making my point! You know to ignore it because | its old, outdated information. | | Then why are you telling me this? How is it useful to me? | | Of course youre up to date with what you last fetched - | that is _always_ the case. | | Why mention being up to date even? Just tell the user | when they last synced with their remote(s). | SAI_Peregrinus wrote: | You're making their point! `git status`tells you the | status as of whenever you last fetched, and omits that | timestamp. You can't tell if it's outdated, because it | doesn't tell you when the last update was! | mjochim wrote: | > Of course youre up to date with what you last fetched - | that is _always_ the case. | | But that is not what this message is about. It's | confusingly worded, as many people agree, but what it | says is that your local ref "main" points to the same | commit as your local ref "origin/main." It says nothing | about "main" on the other computer/server. | | And it is not the case (i.e. you are not up to date with | origin/main), for example, when you have committed to | main but haven't pushed. It is also not the case when you | have fetched but not merged. | ksenzee wrote: | > Of course youre up to date with what you last fetched - | that is _always_ the case. | | This might be where the misunderstanding is. You are | _not_ always up to date with what you last fetched. Say | you have develop checked out, and you run a git pull. As | part of that process, git checks the status of all | upstream branches, and updates your local reference copy | of them (that's what origin /develop, origin/production, | origin/feature-branch-1 are: your local reference copies | of upstream). Then you check out production, which you | last touched two weeks ago. Git will let you know that | your two-week-old local copy is behind origin/production, | which is your local reference copy of what it just saw | when it fetched from upstream. | globular-toast wrote: | Git is a distributed system by design. | | A problem it has is there is now a generation of developers | who don't know _why_ we don 't use centralised VC any more. | Y-bar wrote: | Yes. Which is why temporal data and status is so | important and makes things worse when left out. | yCombLinks wrote: | Everyone uses git as a centralized vcs. You could remove | the distributed part and 99% of people wouldn't notice. | The killer feature was branches, which are orthogonal | globular-toast wrote: | Case in point. I take it you don't remember (or don't | know) that truly centralised systems like Subversion | required a network connection just to make a _commit_? | The commit happened in the repository. There was no local | clone. You could check stuff out. That was it. | yCombLinks wrote: | Yeah, I've used subversion a bit. The DAG aspect and | commits do not require a distributed system. I'm talking | about the idea that git users would pull commits directly | from other users and "build consensus" across the | network, rather than push and pull from a central repo | toast0 wrote: | I mean, we use whatever the boss tells us to, because | that's how a job works? | | git has a better experience than cvs or svn if you're far | away from the VCS server, but that was solvable by having | dev machines near the VCS server. I've gotten used to the | git workflow, but it still doesn't strike me as uniformly | better, other than if you're using git, you don't have to | deal with everybody always ask why aren't you using git. | capableweb wrote: | > Is it though? | | Yes, yes it is. | | origin/master is not saying that the remote has/hasn't | changed. It's comparing your local copy of origin/master, | not giving you the status about if remote has/hasn't | changed. You need to explicitly ask if remote/origin/master | has changed or not if you want to know. | | Which in your analogy would be like if the store forgot to | actually ask the bank if the customer had the money or not, | and instead relying on whatever information they have | "cached" in the store. Instead, the store has to first ask | the bank (remote) if there is any changes. | | I do agree that it could be worded better to actually help | the user understand, as it seems to be a common | misconception. | | Sidenote: I'd be driven to absolute insanity if `git | status` started doing remote requests to check the remote | origin/master status each time I invoked it. | cesarb wrote: | > origin/master is just a file on your system | | Unless it's a packed ref (https://git-scm.com/docs/git-pack- | refs), in which case it's just a line in the packed-refs | file. | e40 wrote: | > I just "pull" every time | | I hope you "git pull -r" every time. Merges are almost always | unwanted. | flostk wrote: | That's just saying git doesn't connect to the internet (or | whereever the remote is) to check for updates without you | explicitly telling it to. I think that's a desirable property, | though the message could be clearer. | leni536 wrote: | What I do is I delete the local master branch. I typically | can't push to master, or I don't want to work on master | directly anyway, so why have a local mutable master branch? So | I only need to update origin/master, which I can do with fetch. | kbknapp wrote: | Git terminology is a clinical example where many (most? | definitely not all) terms make perfect sense _once you already | understand how it works_ , but make almost no sense in concert | with other terminology or when you don't know the implementation | details. | | Leaky terminology. | jordigh wrote: | In part, but also, it's because different people worked on | different parts of git and came up with different names. Linus | originally called it the cache, the most computer sciency term, | and then I think Junio renamed it to index, a more DVCS- | specific term, but most users called it the staging area, and | now the evolution of this term is fossilised into the git UI as | well as its internals. | tester756 wrote: | So basically poor API design | | Imagine if you had to know OS/IDE/compiler internals for basic | usage | KingMob wrote: | As always, here's a link to the helpful https://ohshitgit.com | michaelkaufman wrote: | Dear AI, it would be nice to just use an English prompt, like: | 'put the work I just did onto the Develop branch, even though I | forgot to make a separate branch for it first'. Somebody must be | making a Git-AI, right? | mparnisari wrote: | I always get 'git restore' and 'git reset' mixed up. I just want | to undo my changes dammnit | tornato7 wrote: | The GitHub Desktop app changes some terminology to make it more | usable, for example "Undo" instead of "reset HEAD~". I typically | make aliases for this sort of thing in my terminal, but it would | be great if some of those made it to the Git CLI. | tombert wrote: | I think I have a case of "Git Stockholm Syndrome"; I don't find | any of these terms terribly confusing, but I think that's in no | small part because I haven't really learned any other systems, | and have been entrenched in Git since like 2011. | | Looking back, I suspect that I was extremely confused when | starting out, but was pretending I wasn't to try and seem cool. | raincole wrote: | The only other version control that I used is Plastic SCM, and | honestly Stockholm Syndrome or not, I like git much more. | tombert wrote: | Someone told me that I really need to check out Mercurial for | its binary diffing stuff, and as I've gotten more into 3d | modeling in the last year then that might actually buy me | something. | | However, now that bitbucket has dropped Mercurial support, | I'm not entirely sure where I can easily push a mercurial | repo for backup. For better or worse, I am extremely | dependent on Gitlab to backup my code so I'm not risking my | work on a potentially failing hard disk/ssd. | raincole wrote: | > 3D modeling | | I don't know. For large binary files I still use Google | Drive as backup (I know 3D models are not necessarily | "large" by today's standard) | | One can use git LFS, but there isn't an easy way to free up | the storage them occupy from the history. And GitHub LFS is | about 5 times more expensive than Google Drive per GB. | tombert wrote: | These are just CAD-style models for functional robotic | parts, not game assets or anything, so they're not | actually very large as they're pretty utilitarian, but | they do change a lot. As of right now, I'm just pushing | the binary files to Gitlab with vanilla git, and at least | thus far Gitlab hasn't complained to me. | | I figure that the moment Gitlab sends me a nastygram | about it, I'll move to S3 or Google Storage or something. | pseudalopex wrote: | https://wiki.mercurial-scm.org/MercurialHosting | jeltz wrote: | I had used cvs and svn before I used git, and compared to svn | git was much easier to understand. | bad_username wrote: | I knew that I had Stockholm syndrome when I took a look at the | CLI of the Fossil VCS. It is so... straightforward. | tombert wrote: | Fossil looks neat, but it didn't look "sufficiently better" | than Git for me to bother changing, especially due to all the | services that support Git out of the box. | | What does Fossil buy you over Git? | PH95VuimJjqBqy wrote: | in terms of Fossil as an SCM, it's very similar outside of | the author's views of rebase (which I happen to agree | with). | | https://fossil-scm.org/home/doc/trunk/www/rebaseharm.md | | In terms of Fossil as a technology, it's an SCM with built- | in project management tools (wiki, forums, bug tracker, | etc) so it does much more than git does. | | The front page has more info: | | https://fossil-scm.org/home/doc/trunk/www/index.wiki | globular-toast wrote: | I'm usually the "git guy" so having something like this to refer | to when people ask me about such things will be really useful. | Thanks! | | One of the problems I have is figuring out how people get | themselves into such situations. Like if someone submits a merge | request and their branch looks like it's been merged into itself | with one side rebased or something. When I ask them what they did | they have invariably forgotten. If someone cooked a dish that was | too salty I'd be able to tell them "try putting less salt in less | time". I wish I could do the same with git. | | Although upon typing this I'm thinking perhaps I could figure it | out by looking at their reflog? But that involves accessing their | computer or walking them through it which would probably confuse | them even more. | jkingsman wrote: | > When you configure a git remote in .git/config, there's this | | > +refs/heads/main:refs/remotes/origin/main thing. | | > | | > [remote "origin"] | | > url = git@github.com:jvns/pandas-cookbook | | > fetch = +refs/heads/main:refs/remotes/origin/main | | > | | > I don't really know what this means, I've always just used | | > whatever the default is when you do a git clone or git remote | | > add, and I've never felt any motivation to learn about it or | | > change it from the default. | | This is a refspec[0], and it tells Git the relationship between | local references and remote references, defined in the pattern | [+]<src>:<dest>. So, in this case, it defines the local head of | main to refer to the remote branch main on origin. You could, for | example, define all branches on local as linked to all branches | on the remote with +refs/heads/*:refs/remotes/origin/*. | | An example of a real world usage of this was when we were | migrating our repo between providers -- configuring the fetch | field to link a different remote for different branch names kept | things simple for our developers as we quietly moved branches to | the new remote. | | It also configures the scope of a git fetch command, iirc, so you | can restrict your fetches to only scopes that you care about | (maybe your team has a branch name prefix/namespace that you can | specify, so when you git fetch you only get things that are | relevant and not some other teams' branches you don't need). | | [0]: https://git-scm.com/book/en/v2/Git-Internals-The-Refspec | adhesive_wombat wrote: | As with all these posts, use the git lola alias regularly and all | becomes clear as you can see where all the branches locally and | remote are and how they change when you do things. | | http://blog.kfish.org/2010/04/git-lola.html | mc10 wrote: | In this section: | | > I think in the context of the merge commit ours/theirs | discussion earlier, HEAD^ is "ours" and HEAD^^ is "theirs". | | Should HEAD^^ be HEAD^2 instead? | jvns wrote: | fixed, thanks! | ketzo wrote: | I so appreciate Julia's authorial voice. She does such a great | job writing content that's super valuable for even veteran devs, | while maintaining a tone that's friendly to the newest people in | the field and actively includes them rather than gatekeeping. | kazinator wrote: | Regarding "rebase --onto" | | > _Imagine that for some reason I just want to move commits F and | G to be rebased on top of main. I think there's probably some git | workflow where this comes up a lot._ | | This comes up for me in a branch where I have some necessarly | local changes which are permanently there and have to be | maintained, and that branch experiences non-fast-forward changes | from upstream. | | Say we are up-to-date in this branch, plus our two local commits | that are not in upstream. | | We do a fetch. Upstream has rewritten 17 commits. So now we have | 19 diverging local commits. We only care about two of them. We | just want to accept the diverged upstream commits, and then | rebase the two on top of that. | | We do not want to rebase all 19 commits! | | We can do: git rebase HEAD^^ --onto origin/master | | So HEAD^^ is the "upstream" here that we have explicitly | specified. So following the documentation: | | - All changes made by commits in the current branch but that are | not in <upstream> are saved to a temporary area. | | [That's precisely our two local commits; those are the ones not | in HEAD^^] | | - The current branch is reset to <upstream>, or <newbase> if the | --onto option was supplied. | | [We did specify --onto, so the current branch goes weeee... to | origin/master, the abruptly updated, non-fast-forward upstream | that we want to catch up with.] | | - The commits that were previously saved into the temporary area | are then reapplied to the current branch, one by one, in order. | | [That's the cherry-picking that we want: our two local commits.] | | So end result is that our branch is now the same as origin/master | (up-to-date) plus has the two needed local commits. | | Further, I have a situation in which there are two git repos on | the same machine which have a different version of a local | commit. One of the repos (A) is an upstream for the other (B). | | When B does a fetch, it gets the master branch from A with A's | local commit, which is unwanted in B. B has its own flavor of | that commit: git rebase HEAD^ --onto | origin/master^ | | takes care of it. We catch up with origin/master, but ignoring | one commit, and on top of that we cherry pick ours. | chrisbrandow wrote: | This is really great! | | I'd suggest one edit in the first entry: | | "heads" are "branches" --> a "head" is the end of any given | "branch" | | This makes it a little clearer when talking about detached head | state, since switching to a commit on a _branch_ can still leave | you detached. | | I was confused by that when I got to your detached head | description, so I double-checked. | e40 wrote: | > "heads" are "branches" --> a "head" is the end of any given | "branch" | | and throw "tip" in there, as in "HEAD is the tip of the current | branch". | ryeights wrote: | That's not quite right is it? HEAD is simply a pointer to | whatever commit is currently on disk. | | HEAD _can_ point to a commit that is the end of a branch | (typical state, HEAD is "attached"), but it can also point to | one that isn't (HEAD is "detached"). | Zigurd wrote: | Git has proven to be impervious to designing a discoverable | visual UI. All the ones I have used are fine if you understand | git. But put a naive user in front of a git GUI and they are | almost as confused, just differently. It would be wild if git | turned out to be something that just can't be made visual. But I | suspect the task of making git n00b friendly was never taken | seriously. | tobyjsullivan wrote: | The most valuable step in learning git is having the right mental | model: it's all graphs. | | This tool gets shared a lot and it feels appropriate here. It | visualizes the underlying git model and the effects of various | commands. | | https://learngitbranching.js.org/ | | I learned more from 10 minutes with this tool than the preceding | ~10 years of git experience. Can't recommend it enough. | japhyr wrote: | I've been using Git pretty much since it came out, and I just | learned about "porcelain" this week. I have a project that | involves parsing the output of `git status`, and adding the | `--porcelain` flag is really helpful. It generates a more concise | output that's easier to parse programmatically. | | I wondered how many commands have a more machine-readable output, | and that led me to the git-scm page "Git Internals - Plumbing and | Porcelain". In summary, Git was originally written as a toolkit | for dealing with version control, rather than a polished version | control system. Many of us who used Git from the early days | learned to do VCS work with these lower-level commands, and we've | passed those workflows on to many other people as well. This is | the "plumbing" layer. Git later developed a more polished layer, | referred to as the "porcelain". | | I'm not entirely clear yet on which commands are part of which | layer, but this helped me make sense of the newer workflows I've | seen recommended in recent years. It also gives me a better way | of reasoning about possible changes to my own workflows. | | https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Po... | taocoyote wrote: | Literally potty humor. | ulizzle wrote: | This is why I gave up a long time ago and learned to love the | GUIs. | phendrenad2 wrote: | Git is so integral to software development, I find it hard to | imagine anything else. But I firmly believe that there must be a | better way. Whatever people used before git (perforce?) was | working fine, let's use that. | FranklinMaillot wrote: | The "Missing Semester" is a collection of video lectures from MIT | that covers the fundamentals of command line, git, vim, and other | tools often overlooked in computer science courses. As a self- | taught developer, I found it to be an ideal introduction to git. | | The series made me also pick up vim, and I have not looked back | since. | | https://youtu.be/2sjqTHE0zok | sleepybrett wrote: | My constant git commandline annoyance is that some commands take | remote branches as `origin mybranch` and some take | `origin/mybranch` .. maybe there is an arcane reason for this, | but I've never seen it. | qsantos wrote: | Because they are referring to different things. `mybranch` is a | reference in your local repository. `origin/mybranch` is a | reference on a remote repository that you call `origin`, | `origin/mybranch` is just a representation of this remote | reference for convenience. | | So, if we take the example from derefr [1], `git chekcout foo` | lets you go to your own local branch `foo`. Then, `git reset | --hard origin/foo` modifies the current local ref (`foo`) to be | the same as `origin/foo`, and change the working directory | accordingly. | | [1] https://news.ycombinator.com/item?id=38118475 | permo-w wrote: | perhaps I'm misunderstanding, but this doesn't read so much | as why as it does a rephrasing of the problem with an example | zufallsheld wrote: | I _think_ origin /mybranch is a ref to a commit that was the | current one when you last did a git fetch. `origin mybranch` | fetches the latest commit from the origin. | skeaker wrote: | This one gets me constantly even after using Git for nearly a | decade. My workflow where I try it one way and then the other | is uncannily similar to how most people have to flip a USB at | least once to get it plugged in. No idea why it's like this. | infogulch wrote: | I'm watching Jujutsu / https://github.com/martinvonz/jj as a git- | compatible wrapper/porcelain that adds some important features | and fix a bunch of what is confusing about git: | | It explicitly models conflicts, so you can e.g. send your | conflicts around and aren't forced to deal with them immediately. | | It tracks and logs all repo state including repo operations | (checkout, rebase, merge, etc) and those state changes can be | manipulated and reverted individually just like commits. | | The working copy is automatically committed, and operations | typically amend that latest commit. This alone like halves the | number of unintuitive concepts new users need to learn. Combined | with robust history rewriting tools this makes for a much better | workflow. | tomcam wrote: | Come to think of it, "Detached head state" sounds like a line | from a 1980s action movie | Cthulhu_ wrote: | Or a Meshuggah or Fear Factory track | jroseattle wrote: | I'd prefer to hear everyone's home-cooked list of aliases to | encapsulate all the git command-line funkiness. I'll start: | - last: `git log -1 HEAD --stat` - past: `git log | --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]" | --decorate --numstat` - save: `!git add -A && git commit -m | 'save'` | | (Hat tip to those who helped me with these. I stand on the | shoulders of giants.) | Cthulhu_ wrote: | The save command can be rewritten to 'git commit -am "save"' | for brevity (caveat: I don't know if -A is different from -a | for the two commands). | xorcist wrote: | Not really. It's in the manpage: commit -a | Tell the command to automatically stage files that have been | modified and deleted, but new files you have not told Git | about are not affected. add -A Update the | index[...] This adds, modifies, and removes index entries to | match the working tree. | | So commit -a won't track new files, but add -A will. | jheriko wrote: | HEAD - something you only need to know about when easily fixed | usability bugs in git make your life a misery ___________________________________________________________________ (page generated 2023-11-02 23:00 UTC)