[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)