[HN Gopher] Oh Shit, Git?
___________________________________________________________________
Oh Shit, Git?
Author : Anon84
Score : 421 points
Date : 2025-01-16 18:24 UTC (1 days ago)
(HTM) web link (ohshitgit.com)
(TXT) w3m dump (ohshitgit.com)
| divbzero wrote:
| This is old school. No switch or restore here.
| pitaj wrote:
| Some changes I would make:
|
| 1. Always use `git switch` instead of `git checkout`
|
| 2. Avoid `reset --hard` at all costs. So for the "accidentally
| committed something to master that should have been on a brand
| new branch" issue, I would do this instead: #
| create a new branch from the current state of master git
| branch some-new-branch-name # switch to the previous
| commit git switch -d HEAD~ # overwrite master
| branch to that commit instead git switch -C master
| # switch to the work branch you created git switch some-
| new-branch-name # your commit lives in this branch now :)
|
| 3. I'd apply the same to the `cherry-pick` version of
| "accidentally committed to the wrong branch":
| git switch name-of-the-correct-branch # grab the last
| commit to master git cherry-pick master # delete
| it from master git switch -d master~ git switch
| -C master
|
| 4. And also to the "git-approved" way for "Fuck this noise, I
| give up.": # get the lastest state of origin
| git fetch origin # reset tracked files git
| restore -WS . # delete untracked files and directories
| git clean -d --force # reset master to remote version
| git switch -d origin/master git switch -C master
| # repeat for each borked branch
| lalaithion wrote:
| The disconnect between git's beautiful internal model of blobs,
| a tree of commits, and pointers to commits, and the command
| line interface is so wild. All of these recipes are unintuitive
| even if you have a firm grasp of git's model; you also need to
| know the quirks of the commands! To just look at the first
| one... wouldn't it be more intuitive for the command line
| interface to be: # this command exists
| already; $ git switch -c some-new-branch-name #
| is there a command that simply moves a branch from one commit
| to another without changing anything else? It feels like it
| should be possible given how git works. $ git move-
| branch master HEAD~
| pitaj wrote:
| I prefer just using `git switch` because it's easy to
| remember the flags (and the position of arguments), but
| you're right, there is a simpler way: git
| switch -c some-new-branch-name git branch -f master
| HEAD~
| DangitBobby wrote:
| You should also be able to do git branch -f
| master origin/master
| pitaj wrote:
| This doesn't work if your local master was already ahead
| of origin
| DangitBobby wrote:
| Indeed, as with all of these examples exceptions will
| apply and, it's a good idea to check the log before
| taking any such action. I believe your example also
| depends on exactly how many commits you've made that need
| to be moved. In any case, it depends on me remembering
| exactly what `~` signifies.
| lalaithion wrote:
| Good to know! Thanks for the tip.
| neild wrote:
| The "move a branch from one commit to another without
| changing anything" command is "git reset".
|
| "git reset --hard" is "...and also change all the files in
| the working directory to match the new branch commit".
|
| "git reset --soft" is "...but leave the working directory
| alone".
| rav wrote:
| Actually, "git reset --soft" moves the current branch to
| another commit, without moving the index (aka staging area)
| along with it, whereas "git reset" (aka "git reset
| --mixed") moves the current branch AND the index to another
| commit. I really couldn't wrap my head around it before I
| had gone through "Reset demystified" [1] a couple times -
| it's not a quick read but I can strongly recommend it.
|
| [1] https://git-scm.com/book/en/v2/Git-Tools-Reset-
| Demystified
| lalaithion wrote:
| git reset only works if you're on the branch you want to
| move, which is why every one of these example flows has you
| create your new branch, then do the reset, then switch to
| the new branch, instead of just allowing you to move a
| branch you're not on.
| rav wrote:
| For move-branch: Use `git branch -f master HEAD~` if you're
| currently on another branch, or `git reset --soft HEAD~` if
| you're currently on master.
| Certhas wrote:
| The real "internal model" of git contains much more
| data/moving parts.
|
| There isn't one tree of commits, there are typically at least
| two: local and remote
|
| Branches are not just pointers to commits, but also possibly
| related to pointers in the other tree via tracking.
|
| Stash and index and the actual contents of the working
| directory are additional data that live outside the tree of
| commits. When op says "avoid git reset hard" it's because of
| how all these interact.
|
| Files can be tracked, untracked and ignored not ignored. All
| four combinations are possible.
| lalaithion wrote:
| None of these seem to preclude a command to make an
| arbitrary branch point to an arbitrary commit without
| changing anything else.
| fragmede wrote:
| This works if the branch exists or creates it if it
| doesn't exist, but not if it's checked out.
| git branch -f branch_name commit
|
| if it's checked out: git reset --hard
| commit
| seba_dos1 wrote:
| > but not if it's checked out
|
| ...and for a good reason that should be apparent to
| anyone who understands git's model (HEAD points to a ref
| in this case, so if you suddenly change what that ref
| points to without updating the working tree you create an
| inconsistency).
|
| You can do that manually of course (with `git update-ref`
| or even a text editor), but then you get to clean up the
| mess yourself.
| thfuran wrote:
| Couldn't head just detach without any consistency issue?
| seba_dos1 wrote:
| Theoretically it could, but that would be a rather
| surprising side effect. You could also check the new
| revision out and leave HEAD intact. Which one of those
| outcomes you would expect and why?
|
| "error: ref in use by higher layers" makes much more
| sense to me in this case.
| Certhas wrote:
| If you buy the "git is just a tree of commits and
| pointers" mental model it's absolutely not a surprising
| side effect but would be the logical thing to expect. I
| moved a pointer to a commit around, why would that change
| where HEAD is pointed.
|
| Turns out it's a tree of commits and pointers to within
| that tree and a master pointer that come in two versions:
| pointing towards the pointers or pointing towards the
| tree. And pointers behave very differently when the
| master pointer is pointing to them...
|
| Elegant. Simple. :P
| seba_dos1 wrote:
| > I moved a pointer to a commit around, why would that
| change where HEAD is pointed.
|
| ...because HEAD points to what's checked out. This
| pointer does not just exist and hang around, it has its
| semantics. Not understanding that reveals flaws in your
| mental model.
|
| Besides, the side affect you find "not surprising" here
| is... rewriting HEAD to change what it points to. Then
| you ask "why would that change where HEAD is pointed".
| Sounds like you may be confused. Are you forgetting that
| a ref may point not just to a commit, but also to another
| ref? This is the _whole idea behind branches_ after all,
| having HEAD point to a ref is exactly what makes branches
| semantically different from tags - if you don 't
| understand it then no wonder you're confused.
|
| When a pointer is in use by higher layers, a good UI will
| prevent you from making direct changes underneath it
| unless you force it or go low-level enough for it to not
| matter. The only sin of git I can see here is that `git`
| command provides you both high-level and low-level
| interfaces to manipulate the data structure you're
| working on with no clear distinction for the user.
| thfuran wrote:
| It doesn't seem surprising to me. It probably ought to
| print ought a warning that head has detached though, like
| some other commands already do. That error message on the
| other hand seems very unhelpful. It's lingo that only
| makes sense if you're neck deep in the plumbing.
| seba_dos1 wrote:
| There's no such message there, it was a description of
| situation written by me. Should have made it clearer I
| guess.
|
| It is surprising. You wanted to edit the value of `main`
| ref, yet suddenly you now edited `HEAD` too without
| meaning it. Bailing out and letting you actually decide
| whether you want to do it or not is the correct thing to
| do for a high-level command like `git branch`
| (alternatively it could ask you what to do
| interactively). If you don't want such safeguards and you
| know what you're doing, use `git update-ref` which will
| happily let you break whatever you want.
| Certhas wrote:
| To me that looks like git is leaking implementation
| details left and right.
|
| So much for "a branch is simply a pointer to a commit"...
| seba_dos1 wrote:
| Do you react the same way when an OS prevents you from
| writing to a file with an exclusive lock placed on it? So
| much for "a file is simply a collection of data stored as
| a single object"...
|
| If a git repo was purely a collection of meaningless
| pointers and graph nodes, git would be a graph
| manipulation utility, not a version control system. The
| fact that some of those pointers have a meaning is what
| makes it useful and it doesn't contradict the fact that
| what you're working on is still just a bunch of pointers
| and nodes.
| karatinversion wrote:
| You are looking for git update-ref
| <branch-name> <commit-sha>
| DiggyJohnson wrote:
| Wouldn't the fail or break under any circumstance where
| they don't immediately share a history?
| jimbokun wrote:
| Are there alternative git command lines that keep the
| beautiful internals, but implement a more elegant and
| intuitive set of commands to manage it?
| dalia-reds wrote:
| Check out jujutsu or jj (same thing). It's its own VCS, but
| it uses git as a backend, so it works with GitHub and other
| git integrations
| stouset wrote:
| Seconded jujutsu. It's 100% git-compatible and one of those
| rare birds that is both _more powerful_ and simpler to use
| in practice due to rethinking some of the core ideas.
| maleldil wrote:
| Another vote for jujutsu. No one else needs to know you're
| using it. You can think of it as just a different CLI for
| git (although you shouldn't mix them). I used to use third-
| party interfaces like lazygit, but I don't need them
| anymore because jujutsu _just makes sense_.
| jonasced wrote:
| Lazygit has a terminal UI but might otherwise be what
| you're looking for:
| https://github.com/jesseduffield/lazygit
| Terr_ wrote:
| > The disconnect between git's beautiful internal model of
| blobs, a tree of commits, and pointers to commits, and the
| command line interface is so wild
|
| Something I heard somewhere that stuck with me: git is less
| less of a Version Control System, and more of a toolkit for
| assembling your own flavor of one.
| JadeNB wrote:
| > Something I heard somewhere that stuck with me: git is
| less less of a Version Control System, and more of a
| toolkit for assembling your own flavor of one.
|
| That's how it is in principle, but it seems to me that
| there aren't that many different CLI "porcelains" in
| practice. Kind of like how Knuth figured people would
| essentially write their DSLs on top of plain TeX, not spend
| most of their time in giant macro packages like LaTeX.
| dragonwriter wrote:
| > That's how it is in principle, but it seems to me that
| there aren't that many different CLI "porcelains" in
| practice.
|
| I think that's because most of the people that make
| custom tooling to support particular workflows build it
| into graphical (including IDE extensions, web-based.
| etc.) frontends, not CLIs.
| lilyball wrote:
| The "move a branch" command is `git push .`. Yes, you can
| push to the current repo. I have a script called git-update-
| branch which just does some preflight checks and then runs
| `git push --no-verify . +$branch@{upstream}:$branch` to reset
| a branch back to its upstream version.
| zahlman wrote:
| > The "move a branch" command is `git push .`. Yes, you can
| push to the current repo.
|
| Wouldn't that copy a branch rather than moving it?
| assbuttbuttass wrote:
| > is there a command that simply moves a branch from one
| commit to another without changing anything else? It feels
| like it should be possible given how git works.
|
| git switch -C master HEAD~
| CharlieDigital wrote:
| What's the problem with `reset --hard`?
| pitaj wrote:
| It leaves behind tracked files that were moved or deleted
| between revisions.
| mrshu wrote:
| Not trying to defend the choice of `git checkout` over `git
| switch` (and `git restore`) but they were introduced in v2.23
| of Git [0], which was released about 5 years ago [1]. If you
| take a look at their help pages, they still include a warning
| that says
|
| > THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
|
| Granted, it has been in there for basically as long as the
| command(s) existed [2] and after 5 years perhaps it might be
| time to no longer call it experimental.
|
| Still, it does seem like `git checkout` might be a bit more
| backwards compatible (and also reflective of the time when this
| website was originally created).
|
| [0]
| https://github.com/git/git/blob/757161efcca150a9a96b312d9e78...
|
| [1] https://github.com/git/git/releases/tag/v2.23.0
|
| [2]
| https://github.com/git/git/commit/4e43b7ff1ea4b6f16b93a432b6...
| baobun wrote:
| 5. Teaching `git add .` as default to add changes to the
| staging area is not ideal. Show adding specific files instead
| has less room for subsequent "oh shit" and better.
| ajross wrote:
| True enough, but it _does_ make for good practice with the
| index and splitting workflows later on when you need to clean
| it up.
|
| I think there's space for "git add ." as a didactic step. It
| maps cleanly to the most obvious way to understand a commit,
| as "here's what I've done". Bootstrapping from that to an
| understanding of "commits as communication with other
| developers" will naturally happen over time.
| baobun wrote:
| Is not very compatible with printlog-debugging. I'd rather
| encourage devs to prod around as they go if it benefits
| them, which causes grief for either them or reviewers in
| the end if they've internalized what you just said.
|
| Explicitly adding internalizes a personal review process as
| inherent part of the push process, instead of something you
| attempt to force on top later.
|
| It's better with a collaboration workflow that limits the
| span of time with expected discipline, imo.
| recursive wrote:
| You can have both. Make sure the whole diff is what you
| want it to be before invoking `add .`
| baobun wrote:
| Sure. I hear the pull-out method is also an effective
| contraceptive.
| zahlman wrote:
| Learning about the `-p` option for `git add` was one of two
| things that revolutionized my Git usage. (The other was
| figuring out how to write effective commit messages.)
| wodenokoto wrote:
| This is the main reason to use a GUI imho.
| baobun wrote:
| Tig is a great one for the terminal fwiw.
|
| gitg for something simple, graphical and widely
| available.
| jaapz wrote:
| Could you motivate why you suggest these? Why is `switch`
| better than `checkout`? And why not use `reset --hard`?
| jopicornell wrote:
| Not comment OP, but checkout has two very different uses
| merged into one: restoring files and switching branches. To
| not break compatibility, git has now switch and restore
| commands that make commands more readable and understandable.
|
| You should avoid reset --hard because it will delete all your
| uncommited, and you could end up in situations where that's
| really bad. Using reset --keep will keep uncommited changes,
| and failing if any uncommited change cannot be kept.
| teaearlgraycold wrote:
| I just do git add -A git
| stash git reset --hard git stash
| pop
| stouset wrote:
| Rewriting these for jj users. I'm prefering long option names
| and full command names for clarity here, but all the commands
| have shortened aliases and all the option names have single-
| letter alternatives. `@` means "the current revision", `x+`
| means "the revision just after `x`", `x-` means "the revision
| just before `x`".
|
| 2. "Accidentally committed something to master that should have
| been on a brand new branch".
|
| This doesn't really have an analogue. Branches ("bookmarks")
| only move when you tell them to. If you make a new commit on
| top of master, it doesn't point master to it, it just lives one
| past the tip of master. But let's say you accidentally moved
| master to include the new commit you shouldn't have:
| # set master to the previous commit (and reaffirm that
| # you're okay moving a bookmark backward) $ jj bookmark
| set master --allow-backwards --revision @- #
| there is no step two, you're still editing the change you
| already were
|
| 3. Move a commit from one branch to another.
| # move the revision one-past-master on to our desired bookmark
| $ jj rebase --revision master+ --destination name-of-the-
| correct-bookmark # there is also no step two;
| technically we're not updating the bookmark # to point
| to the new commit yet, but this isn't something you'd do as
| rote # habit in jujutsu anyway
|
| 4. Fuck this noise, I give up: # list all the
| operations I've performed against the repo $ jj op log
| # restore to some previous known-good state $ jj op
| restore {id}
|
| Bonus content, translated from the article:
|
| > Oh shit, I committed and immediately realized I need to make
| one small change! # move the current edits
| into the previous revision $ jj squash
|
| > Oh shit, I need to change the message on my last commit!
| # re-describe the previous revision $ jj describe
| --revision @-
|
| > Oh shit, I tried to run a diff but nothing happened?!
| # there is no staging area, all your changes are part of the
| repo and there is no # staging area pseudo-commit;
| please understand that this still works elegantly #
| with "patch-add" workflows and does not imply that large change
| sets can't be # easily broken up into small commits
|
| > Oh shit, I need to undo a commit from like 5 commits ago!
| # find the commit $ jj log # back it out
| $ jj backout {id}
|
| > Oh shit, I need to undo my changes to a file!
| # find the commit $ jj log # restore the
| paths provided to their contents in the given revision
| $ jj restore --from {id} [paths...]
|
| And finally there are a few things that are super easy/obvious
| in jujutsu that are far more annoying in git.
|
| > Oh shit, I committed and many commits later realized I need
| to make one small change! # moves the changes
| in the current working copy into the revision provided
| $ jj squash --into {id}
|
| > Oh shit, I committed and many commits later realized I need
| to make extensive changes! # sets your
| working copy to the commit provided; later commits will be
| # auto-rebased on top live as you make modifications $
| jj edit {id}
|
| > Oh shit, I need to reorder two commits! #
| does what it says on the tin $ jj rebase --revision {a}
| --insert-before {b}
|
| > Oh shit, I haven't committed anything in hours but I need
| something from an interim change from like thirty minutes ago
| # look in the "obsolete log" for earlier iterations of the
| current revision $ jj obslog # restore the
| contents $ jj restore --from {id} [paths...]
|
| > Oh shit, I made a bunch of changes but want them to be in
| multiple commits (e.g., patch-add workflow) #
| choose the parts to move out; you'll end up with two revisions,
| one with each half $ jj split
|
| > Oh shit, I need to break out a change from my current work
| into a new branch off master # choose the
| parts to move out; you'll end up with two revisions, one with
| each half $ jj split # move the stuff I
| pulled out onto master $ jj rebase --revision @-
| --destination master # optional: name it; most of
| the time you wouldn't bother $ jj bookmark create new-
| name --revision master+
|
| > Oh shit, I need to make three sequential changes but roll
| them out one-by-one. I also might need to make fixes to
| previous ones before later ones are rolled out.
| # author a new change on top of master and name it a $
| jj new master ... $ jj bookmark create a
| # author a new change on top of a and name it b $ jj
| new ... $ jj bookmark create b #
| author a new change on top of b and name it c $ jj new
| ... $ jj bookmark create c # edit a;
| nothing else is necessary to ensure b and c remain as
| descendants of # revision a jj edit a
| ... # author a new change as part of b; nothing
| else is necessary to ensure c remains # up to date on
| top of b $ jj new --insert-before c ...
| # point c at the new change $ jj bookmark set b
| amanwithnoplan wrote:
| Please kindly write one for a jj-specific issue: "my build
| vomitted out a bunch of files and I used any jj command
| before editing my .gitignore"
|
| I've found myself using git to fix the mess in this
| particular instance.
| stouset wrote:
| $ jj file untrack {paths-or-pattern}
|
| Alternatively if you have a bunch of files spewed
| everywhere with no rhyme or reason which can't be globbed
| or enumerated reasonably: $ jj status |
| grep '^A' | awk '{print $2}' | xargs jj file untrack
| hooper wrote:
| One thing I really appreciate is that you can run `jj new
| master` at _any_ time to drop what you're doing and start a
| new change. The way jj handles the working copy, conflicts,
| and visible heads means there's just no need to think about
| uncommitted changes, unfinished conflict resolution, detached
| head, etc.. So many things that would get in your way just
| can't happen.
| stouset wrote:
| I haven't thought about it at all but you're right. It's
| surprising how _nice_ it is that I can enter a repo and `jj
| new main` without needing to remember any context
| whatsoever.
|
| My post was a pretty naked attempt to showcase how much
| less convoluted basic operations are in jj vs. git and
| hopefully drum up some interest. Hopefully someone bites.
| steveklabnik wrote:
| `jj new trunk()` is even better than `jj new main`, I
| just realized, ha!
| stouset wrote:
| It is! I've fully migrated my repos over to `main` at
| this point so it's rare I have to think about the
| difference. You could also make an alias to `jj n` or
| something to make it even easier.
| dustingetz wrote:
| millennial boomer here where is the gen z cheat sheet for this
| git switch thing that i keep hearing about
| ajross wrote:
| > 1. Always use `git switch` instead of `git checkout`
|
| Even harder: always use "git reset --hard".
|
| Basically don't use local branches. The correct workflow for
| almost every task these days is "all branches are remote".
| Fetch from remotes. Reset to whatever remote branch you want to
| work above. Do your work. Push back to a remote branch (usually
| a pull request branch in common usage) when you're done.
|
| If you need to manage local state, do it manually with tags (or
| stash, but IMHO I never remember what I stashed and will always
| make a dummy commit and tag it).
|
| Don't ever try to manually manage a branch locally unless you
| (1) absolutely have to and (2) absolutely know what you're
| doing. And even then, don't, just use a hosted upstream like
| github or whatever.
| smrq wrote:
| This sounds like the correct Git workflow if you think the
| correct VCS to use is SVN.
| ajross wrote:
| And that sounds like you failed to understand me. I didn't
| say "don't use branches". I said "all branches are remote".
| Pushing to a branch is communication with other human
| beings. Mixing your own private state into that is
| confusing and needless in 99% of situations (and the
| remaining 1% is isomorphic to "you're a maintainer curating
| branches for pushing to other people at a well-known
| location").
|
| All branches are public.
| ryandrake wrote:
| I have quite a few projects that do not have a "remote"
| and will probably never have a remote repo. Should I not
| be using branches at all?
| simoncion wrote:
| > All branches are public.
|
| What actual problem does this solve? For me, WIP branches
| only ever get pushed up if at least one of two things are
| true about them:
|
| 1) They're actually worth preserving, and not some
| experimental garbage that ended up being totally
| pointless.
|
| 2) I need to get them off of my local machine for
| disaster-recovery purposes.
|
| > If you need to manage local state, do it manually with
| tags (or stash, but IMHO I never remember what I stashed
| and will always make a dummy commit and tag it).
|
| I don't see the benefit one gets from putting work that's
| not fit for publication in a dummy commit on a public
| branch. That's just _asking_ for garbage that noone
| should concern themselves with to accidentally get pushed
| up at the end of a long-ass day.
| ajross wrote:
| > 1) They're actually worth preserving, and not some
| experimental garbage that ended up being totally
| pointless.
|
| That seems naive. You don't know what's pointless for
| _years_ , usually. Can I tell you how many times I've
| gone back to stale pull requests and topic branches to
| recover "How did I do this?" code?
|
| > 2) I need to get them off of my local machine for
| disaster-recovery purposes.
|
| That's called a "backup", and yes, data robustness is a
| big advantage of this workflow. You're acting like this
| is some kind of rare event. I push my local work to a
| branch (or three) on github every hour!
|
| A corrolary is hardware independence, btw. Working off
| remote branches means I can also stand up a replacement
| development environment with a simple clone. (And the
| corrolary to _that_ means that I can trivially document
| this such that _other_ people can stand up development
| environments for my stuff, too!)
| snafferty wrote:
| This is a workflow I've never seen on any team or project
| I've worked on. Another commenter already mentioned the
| remote branch for everything preference, but usage of tags is
| especially interesting to me. I think that's how most people
| use branches, and tags tend to be more permanent. What do you
| do when you come back to the commit with the tag, cherry pick
| it over and delete the tag? It sounds like an overly
| complicated process compared to having a branch and rebasing
| onto the current branch when you finally go to make the
| change for real.
| ajross wrote:
| Local branches aren't names for anything other humans
| beings care about. All "branches" discussed in a team are
| remote. But because branches have "history" and "state",
| keeping your local names around is just inviting them to
| get out of sync with identically or similarly-named
| branches out there in the rest of the world.
|
| > It sounds like an overly complicated process compared to
| having a branch and rebasing onto the current branch when
| you finally go to make the change for real.
|
| Not sure I understand the problem here? The rebase is the
| hard part. It doesn't help you to have a name for the code
| you're coming "from". If it collides it collides and you
| have to resolve it.
|
| What I said about tags was just as short term memory "This
| commit right here worked on this date", stored in a way
| that (unless I delete or force-update the tag) I can't
| forget or pollute. Branches don't have that property. And
| again _local_ branches don 't have any advantages.
| krick wrote:
| At first I was put aback by this, but it actually kinda makes
| sense. I mean, if people are giving off unwarranted advises
| about "the right way" here, yeah, you _should_ start with a
| remote branch, and push all your work ASAP. Especially when
| you are closing the lid of your laptop to change location.
|
| ...Not that I am gonna follow that advice, of course. Same as
| I 'm not gonna use git switch for a task git checkout does
| perfectly well.
| johnisgood wrote:
| What do you mean avoid "reset --hard"? Why or why is it not
| enough in practice? I use it quite often, along with "alias
| git-restore-file='git restore --source=HEAD --'". It seems to
| work.
| Am4TIfIsER0ppos wrote:
| git switch is too new and its man page says "THIS COMMAND IS
| EXPERIMENTAL. THE BEHAVIOR MAY CHANGE."
| xk3 wrote:
| > 2. Avoid `reset --hard` at all costs
|
| Sounds like you might be looking for `git reset --keep`
| behnamoh wrote:
| Git is one of those technologies that I never got to wrap my head
| around of, because in so many ways it doesn't follow intuition
| and unless you have been using it for a long time, for literally
| every action you would probably have to Google or use the man
| page of the command.
| nomel wrote:
| I was trying to delete a file from history yesterday.
|
| The built in way (filter-branch) pops up a warning, with a long
| delay, saying you should hit Control+C and go download a third
| party python script called filter-repo...
| PaulDavisThe1st wrote:
| Possibly consider that "deleting a file from history" is
| rather far outside the norm or recommended practice for git
| (even though it is, of course, entirely possible)
| nomel wrote:
| > even though it is, of course, entirely possible
|
| I take the more realistic perspective: until git makes it
| impossible to commit something that shouldn't have been,
| like a secret, then deleting a file from history is a
| fundamental requirement of git.
| tom_ wrote:
| The designers of git clearly disagreed, as you can guess
| from its design, so it's not surprising it might feel
| like a bit of an uphill struggle (and will probably
| remain so). There are other tools available.
| lcnPylGDnU4H9OF wrote:
| Even if you purge the history, the secret is compromised
| and you should stop using it. It's moot whether or not
| you're able to remove it from history.
| nomel wrote:
| That's, for secrets. Secrets aren't the only thing one
| might want to remove retroactively.
| bitwize wrote:
| It's ok mate. Hackernews says we should be using jj to manage
| our rewritten-in-Rust code.
| behnamoh wrote:
| Haha, I'm so glad I didn't fall for the whole rust thing.
| stouset wrote:
| Both you and GP, please aim higher for comments on HN.
| iimblack wrote:
| Since you brought it up, I personally switched to jujutsu and
| prefer it greatly. I regularly help coworkers deal with
| issues in git and keep dropping hints like `in jujutsu this
| would've been done way easier like this!`. Nobody bites yet
| since I think most of them don't want to use the CLI but
| maybe someday if enough people keep talking about it the
| inertia will get to the point that we can get some really
| slick GUIs for jj.
| dmd wrote:
| As everyone knows, though, Git gets easier once you understand
| branches are homeomorphic endofunctors mapping submanifolds of
| a Hilbert space.
| wbl wrote:
| That's the Darcs joke and you told it somewhat incorrectly.
| behnamoh wrote:
| Oh geez now that clarifies everything, how could I miss that?
| jimbokun wrote:
| > homeomorphic endofunctors mapping submanifolds of a Hilbert
| space
|
| Has to be easier to understand that then all the arbitrary
| git commands.
| sampo wrote:
| Git commands, while they may be cryptic, actually mean
| something. Whereas that was just gibberish made by putting
| random mathematical words together.
|
| (There is a similar sounding joke about category theory, "A
| monad is just a monoid in the category of endofunctors" but
| this sentence has a mathematical meaning.)
| riwsky wrote:
| Unless you're in a detached HEAD, in which case it's
| xylomorphic to the left-aligned Galois group of R^3.
| stephen_g wrote:
| Did you start with Git or have you used other VCS systems
| before? I started with SVN and then coming to Git, there were
| obviously things to learn about how it was different but
| honestly it felt to me like it made things easier in many ways
| (since I'd experienced the horror of a very large codebase in
| SVN with lots of branches, and trying to track those and merge
| back together - git is so much better at that, it's crazy)...
|
| I can see how it would be a much bigger learning curve if
| people come straight to git, but it's still hard for me to
| understand where the blocker is that so many people complain
| about using it...
| antithesis-nl wrote:
| Yeah, please don't create sites like this. Just... don't.
|
| Any, and I mean _any_ "in case of a Git problem, just do _this_ "
| recipe is _wrong_ , often in very subtle ways. So, my advice: in
| case of a Git problem, contact the help channel provided by the
| organization hosting your Git repository. They'll help you out!
| And if it's your personal-I-am-truly-the-only-human-using-this
| repository? Just recreate it, and save yourself the pain.
|
| Source: I'm part of the team behind the #githelp channel in many
| $DAYJOBs, and _we know_ how hard things are. You committed an
| unencrypted password file, or worse, your entire 'secret' MP4
| collection to our monorepo? Sure, just let us know! Pushed your
| experimental branch to master/main/head/whatever? We'll fix it!
|
| Just don't _ever_ , for whatever reason, run that-chain-of-
| commands you found on the Internet, without understanding what
| they do! In most cases, your _initial_ mistake can be undone
| pretty quickly (despite requiring nonstandard tooling), but once
| you 're three levels deep and four days later, not so much...
| 1over137 wrote:
| We're not all working at $bigcorp with dedicated help teams.
| Sites like this are great and have helped me many times!
| doubled112 wrote:
| What happens when you are the help team and it's the first
| time something goes wrong?
| antithesis-nl wrote:
| A 'team', by definition, consists of more people than
| 'you.'
|
| And, by the time a '#githelp team' is formed, it's to
| address patterns to which there are known solutions.
|
| One of the many problems with Git, is that these solutions
| depend _very, very much_ on the structure of the repo and
| the common practices of its users.
|
| So, instead of executing random commands from the Internet,
| just ask. Please! Or, if there's truly nobody going to be
| around, give in and recreate the repo. You'll save yourself
| so much pain in the long run...
| recursive wrote:
| > A 'team', by definition, consists of more people than
| 'you.'
|
| I'm the resident git expert, but not by choice. There's
| more that I don't know than that I do. It's not uncommon
| that I need to use internet recipes to un-wedge someone's
| clone.
|
| > Or, if there's truly nobody going to be around, give in
| and recreate the repo. You'll save yourself so much pain
| in the long run...
|
| This is insane. There are a dozen other people using the
| remote, not to mention a whole CI/CD build configuration.
| antithesis-nl wrote:
| OK, so you've truly screwed up your your personal/small-team
| repos to the point of requiring poorly-understood command
| sequences from the Notoriously Reliable Internet more than
| once?
|
| I applaud you for your honesty, but... Really?
| jazzyjackson wrote:
| Bro, really, self-taught people with a bare minimum
| understanding of the tools they use are super normal, and
| when they get into a pit they have to fix it themselves.
|
| Although to your point folks would be better served
| carefully reading the docs / git book than googling a
| specific solution to their specific error code.
| antithesis-nl wrote:
| > Bro
|
| Really?
| jazzyjackson wrote:
| I guess we're coming from different places. In my
| vernacular, ending a comment with "...really?" is about
| as casual as calling somebody bro.
|
| It's gender neutral btw.
| leptons wrote:
| "Bro" is the furthest thing from "gender neutral". Not
| sure how you could think it's gender neutral. It
| originated from male behavior and is definitely not
| gender neutral. You can address women as "bro" and they
| might even respond to you but they'll think you're
| absolutely weird.
| jazzyjackson wrote:
| "bro", "bruh", it's more of an exclamation of surprise
| than a title conferred to the person being addressed, but
| even then, I don't know, people call folks "auntie" and
| "uncle" who aren't actually their auntie and uncle.
| language is flexible. it may reference the kind of
| fraternity between brothers but that feeling is not
| limited to the male sex.
| kstrauser wrote:
| Can confirm. It sounds so weird to me, but I hear my kids
| and their friends call each other "bro" or "bruh" all the
| time, regardless of gender.
| guenthert wrote:
| Isn't this like 'guys' including gals a generation
| earlier?
| DangitBobby wrote:
| No, the female and non-binary people in my life both give
| and accept "bro" or "bruh" without complaint. I once
| asked one of my non-binary friends directly how they felt
| about "bro", "dude", etc and they consider those words to
| be gender neutral. They are like the word "man" now ("IDK
| man").
| Terr_ wrote:
| > They are like the word "man" now ("IDK man").
|
| That's actually how it was originally, because in Old
| English "man" just meant a gender-neutral "person."
|
| Gendered versions were "wer" and "wif", so you could have
| a "wer-man" and a "wif-man", the latter changing
| pronunciation to become "woman". I suppose this also
| means that there are both "werewolves" and "wifwolves".
| spokaneplumb wrote:
| I'm about 95% sure that if I ask my two school-age
| daughters if it's weird to address girls and women as
| "bro" or "bruh" in informal circumstances, they'll say
| no. Since I hear them do it with some regularity.
| syndicatedjelly wrote:
| U r
| kstrauser wrote:
| For me, the value of things like this is in learning the
| terminology for what I broke and how to fix it. I'm not
| going to copy-and-paste advice off the Internet. I never
| have. It's still super helpful to see "oh, that thing I
| want to do is called frobnitzing the corple. Now I know
| what to Google!"
| recursive wrote:
| Yes. I think the ratio of small-team repos this describes
| is close to 100%. You seem to have a certain idea of how
| repos are managed. I don't think it's very representative
| of reality.
| zahlman wrote:
| I don't understand your surprise or disbelief. I would
| imagine _most_ devs have been there. As evidence: just look
| at Stack Overflow, and compare it to what it 's apparently
| intended to look like and how it's supposed to work (as a
| denizen of meta.stackoverflow.com I am quite familiar with
| this struggle).
| PaulDavisThe1st wrote:
| I've been using git for at least 6 years now, maybe 10.
|
| Sites like this are a great aid to remembering how to deal with
| certain situations. And yes, I understand what the commands do,
| but that doesn't mean I always could, or always want to, put
| together the series of steps from scratch.
|
| And also, we self-host our own gitea hosting because we're not
| getting sucked down by yet another hosting debacle (old enough
| to have suffered under sourceforge, and don't plan on getting
| in the same situation again). For git hosting just as much as
| everything else on line, if you're not paying for it, you're
| not the customer.
| antithesis-nl wrote:
| > For git hosting just as much as everything else on line, if
| you're not paying for it, you're not the customer.
|
| Yeah, lovely trope, but I'm literally talking about
| organizations hosting their Git repos on a file share here.
| PaulDavisThe1st wrote:
| Why would you ask employees of a file hosting service about
| how to use git?
| jpeloquin wrote:
| Recipes like these aren't useless, but yes, they really need to
| be prefixed with whether they expect to start from a clean work
| tree and empty staging area. Or describe what they'll do to
| uncommitted changes, both staged & unstaged. Otherwise they
| pose a substantial risk of making the problem worse.
| conkeisterdoor wrote:
| > "... or worse, your entire 'secret' MP4 collection to our
| monorepo?"
|
| Oh no, that poor soul...
| divbzero wrote:
| Previous discussions:
|
| _Oh Shit, Git_ - https://news.ycombinator.com/item?id=31874308 -
| June 2022 (232 comments)
|
| _Oh Shit Git?_ - https://news.ycombinator.com/item?id=24173238 -
| Aug 2020 (156 comments)
|
| _Oh shit, git (2016)_ -
| https://news.ycombinator.com/item?id=19906972 - May 2019 (277
| comments)
|
| _Oh shit, git: Getting myself out of bad situations_ -
| https://news.ycombinator.com/item?id=15951825 - Dec 2017 (509
| comments)
| Rooster61 wrote:
| Unable to access this. Might be hugged to death
| tonymet wrote:
| https://archive.is/qXlY7
| Retr0id wrote:
| my main use case for LLMs these days is asking it how to (un)do
| things with git
| tantalor wrote:
| I'm not a git user, but stuff like this really drives home the
| idea that "git commit" is meaningless, the only thing that
| matters is when your commits are pushed or merged.
|
| It's like saving a textfile. Do you write a little message every
| time you save a file? No that's silly. Just move on.
| trashburger wrote:
| If I'm saving changes that were done because of a arduous
| debugging journey and other people are likely to have to refer
| back to it, yes. In fact, forget little; the smaller the change
| is, the bigger the text. Some of my changes have 2-3 paragraphs
| for a 2-3 line change because of the impact.
| kstrauser wrote:
| Same here. If it took me a week to figure out why to tweak a
| couple lines of code, I'm going to be explaining it.
|
| (Although also/mainly in the comments if it's something I
| worry someone might accidentally change back later.)
| shuntress wrote:
| Well, it is all local until you push so you can do whatever you
| want.
|
| With that said, it obviously is not meaningless at a technical
| level because without the commit there is nothing to push or
| merge. On top of that, at a non-technical level it can be
| extremely helpful to record some plain-english prose to
| describe why you are changing something. If you find yourself
| doing that too often you need to narrow your definition of what
| constitutes a "change" and/or be more discerning about what you
| work on simultaneously.
|
| Out of curiosity, if you do not use git, what do you use for
| version control and change-management?
| globular-toast wrote:
| Commit is what causes git to make a copy of the file(s)
| internally. It's vitally important. But there is no point
| typing in silly messages like "more fixes" etc. What I do is
| make an initial commit with something like "(WIP) too feature",
| then keep doing amend commits until I'm happy, at which point I
| remove the "(WIP)" from the message.
| julianeon wrote:
| I actually use git for my todolist/diary and I have an alias
| for when I want to save which does git commit -m "whatever."
| Basically I do that so I can view the updated version in the
| mobile app.
| Vampiero wrote:
| It seems painfully obvious to me that local and remote commits
| serve different purposes. Local commits are a way to create
| checkpoints when everything compiles and works and you can move
| on to the next step. That way you can stash your changes and go
| back to a working state when you screw things up. Then, before
| you push those changes, you reset them and split them into
| proper commits. That way the history is all nice and clean on
| the remote and it's not just a bunch of "wip"s.
|
| Or you can just squash-merge your PRs and reap both benefits.
| Nullabillity wrote:
| Even better, `git merge --no-ff` your PRs and use `git log
| --first-parent` for the simplified "as-if-it-was-squashed"
| history.
| MetaWhirledPeas wrote:
| I think people would generally have an easier time with git
| if they didn't try to fix their commit histories and instead
| just let their past mistakes be known. If you make a bad
| commit in git the best solution is to follow it up with a
| good one that fixes the problem. Squash commits on PRs help
| too.
| nejsjsjsbsb wrote:
| I have no pride. I push my dumb commits that chronical my
| weird journey full of sub-junior mistakes to get to the final
| state.
| zahlman wrote:
| >It's like saving a textfile. Do you write a little message
| every time you save a file? No that's silly. Just move on.
|
| Do you write a little message about your day every time you go
| to sleep?
|
| I actually don't, and maybe you don't, but plenty of people do.
|
| I think of the Git revision log as much like that sort of
| diary, offering the same sorts of advantages. It's more
| organized than having a separate TODO list document; and it
| encourages you to describe what you've already done in a clear
| readable way, too. When you're trying to figure out how far to
| roll back, it may be useful to understand what you were
| thinking at the time of the commit. And if something turned out
| to be the wrong approach, it helps you do the post-mortem.
|
| And, of course: if your unmerged, unpushed work is organized
| into separate changes that have separate (and labelled goals),
| and part of that work turns out to be good and part bad, it
| becomes vastly easier to preserve the good parts.
| tonymet wrote:
| github's "reflog" is the activity log API
| https://docs.github.com/en/rest/activity?apiVersion=2022-11-...
|
| Useful in case someone force-pushes and no one has the good ref
| locally.
| SebastianKra wrote:
| We should start recommending UIs as the default way to learn Git.
| It would solve a third of these problems and another third
| wouldn't even come up.
|
| If you later decide that the CLI is faster, go ahead. But first,
| people need to _see visually_ how they can interact with the
| tree.
|
| I like fork.dev, but most clients are pretty similar at this
| point.
| nuancebydefault wrote:
| The cli is faster if you know by heart but a real disadvantage
| is that it is hard to "see" what you did or what happened in
| the past. Good look finding where/whether an old branch got
| merged and find out if it is part of a release, using cli.
| harrall wrote:
| Is this really true? When I want to reorder commits, I just
| drag & drop in a GUI and I'm done. Or if I want to switch
| branch or manage a complex mix of rebases or cherry picks,
| it's just 2 or 3 clicks. In CLI, by the time I've typed out
| the commit hash or locator, it's already taken longer. And I
| type 130 words per minute.
| dijksterhuis wrote:
| > by the time I've typed out the commit hash
|
| i don't think i've typed out a full hash in ... years? if i
| have i've used the short 8 character hash.
|
| git rev-parse might be something useful to have a look at,
| especially when combined with aliases.
| harrall wrote:
| Nah I'm talking about the short hash.
|
| But I still have to find the short hash too, and then
| copy or re-type it... With a UI, I just... click click
| click done.
| globular-toast wrote:
| As a magit user I agree, apart from the fact most GUIs I've
| seen are horrendously broken and can lead to an even worse
| mess. For example, I was really confused about how a colleague
| messing up and got them to show me. Turns out in VS Code if you
| set the upstream branch correctly (ie. to master), it tries to
| get you to "sync" the branch. So it assumes the upstream branch
| is the branch you push to, which makes no sense at all.
| koito17 wrote:
| Agreed that UIs generally provide a better UX for Git.
|
| I use Magit and doing things like "abort cherry-pick" is
| _discoverable_ in the interface itself and uses the exact same
| shortcut as the other "abort X" operations. If I had to use
| the Git CLI, I'd have no idea where to start.
|
| Similarly, I've made mistakes in interactive rebases where I
| deleted a commit that shouldn't have been deleted. If I recall
| correctly, the start of every rebase creates a snapshot that is
| accessible from the reflog, so this is a safe way to revert
| changes from a rebase gone wrong. Magit's UI for the reflog is
| exactly the same as the UI for the log, so I was not lost when
| I saw it for the first time. With the Git CLI, I'd likely have
| no clue what's going on.
| JTyQZSnP3cQGa8B wrote:
| I agree, I have used git for more than 10 years and it's the
| only tool that I refuse to learn. The command-line interface is
| cryptic and infuriating. I'd rather write assembly language
| again than learn what is essentially a CLI to the internals of
| git. It's not high-level, it's not intuitive, and it can be
| destructive if you don't use the right option. I stick to GUIs
| and simple actions, and I never had any problems compared to
| all the horror stories of my CLI-loving coworkers.
| taberiand wrote:
| I advocate this with every newbie to git - find a UI that works
| for you and use it over the cli. Barely anyone listens though,
| and then they struggle with the cli and make a mess of their
| branches and fall out of date with main and are scared of
| rebasing and have many other issues that are solvable with a
| drag and drop or similar in a UI. I figure it's a sort of
| masochism.
| MrJohz wrote:
| I've started recommending jj as a (git compatible) alternative
| to git, and one of the things I like about it is that the
| default action if you run `jj` with no arguments shows the
| relevant parts of the commit tree and where you are in it. This
| is a great reorientation tool, because you can see at a glance
| which commit you're working on right now, the branches and
| history associated with it, any other active branches in your
| repository, and for each you can see whether each commit had
| messages, changes associated with it, etc.
|
| It's really powerful because it gives you precisely that visual
| layout that shows you what's going on in the repository, and
| what you're doing right now.
| marssaxman wrote:
| I have not used such a tool in a long time, and never with git:
| but my past experience with GUI frontends for version control
| was that they work fine when everything is working fine, but
| once you have a mess to clean up, nobody can help you.
|
| It has generally worked better for me to use the same interface
| everyone else is using, even when that interface is awful,
| because that eases communication with the rest of the team. It
| also lets me take advantage of online troubleshooting
| resources, which all assume you are doing things the normal
| way.
| FractalHQ wrote:
| lazygit ! Just needed to throw out a mention because it's an
| amazing tui for visual orientation, is super fast, and can be
| used with a mouse and keyboard (or just keyboard) from the
| terminal. I saw it mentioned on a thread here last year and
| have preferred it as a fast "oh crap I think I made a mess lets
| back up" tool over the more complex gui apps I've tried (almost
| all of them).
| dijksterhuis wrote:
| disagree, with a caveat.
|
| to summarise: use the desktop apps now, but thou shalt need to
| learn the CLI.
|
| --
|
| when i've taught absolute development beginners how to use git
| and how to do PRs i show them both the CLI and GitHub desktop.
| not every single thing. but i at least show them
| add/commit/push and creating/checking out branches in the CLI.
|
| why?
|
| 1) this CLI thing is what power users / experienced folks use.
| this is your long term goal.
|
| 2) oh look, the terminal is typing things out instead of
| clicking on buttons which have slightly different names (target
| audience has never seen a terminal)
|
| 3a) some things cannot be unfucked in a desktop app. i don't
| have to explain what the CLI is to show them how to unfuck it.
| i might have to remind them. but it's not totally alien to
| them. they're only seeing the fix for the first time, not the
| fix _and_ the CLI.
|
| 3b) they might feel more comfortable trying to use the CLI when
| they've already been shown it before. ideally in tandem with 3a
| -- "hey i need to do this thing to unfuck it, could you sit
| with me while i go through to avoid fucking it even more"
|
| 4) maybe they go "screw it, i want the pain because i really
| want to be a magician at this". it's nice for them to have the
| _option_ of the easier, simpler path when they're having a bad
| day with it.
|
| ill always suggest that absolute beginners _use_ the desktop
| apps because it does reduce early fuck ups. and part of that
| involves showing them the desktop apps.
|
| but i feel they need to be made aware the desktop apps are not
| the be end and end all. they can try the CLI a few times if
| they want. at some point, they will have to use it.
|
| they also need to learn to fuck it up. making mistakes is how
| human beings _really_ learn.
|
| both making mistakes and demo-ing the CLI early, often and
| safely; rather than later and rarely; gets people to "magician"
| level faster in my experience.
|
| essentially, you have more to learn buddy. keep working on it
| if you want to be one of the magicians in the team. if you
| don't, that's fine. but at some point you'll need to deal with
| this CLI thing.
|
| --
|
| > people need to see visually how they can interact with the
| tree.
|
| i've got a whole diagram thing i draw live showing them how
| everything is based on commits or a collection of commits,
| moving the commits around in front of them.
|
| seems to be a better way to cover remotes, branches and
| eventually PRs than leaving them to work it out with some
| history visualisation which is usually a bit hard to read.
| Izkata wrote:
| > But first, people need to _see visually_ how they can
| interact with the tree.
|
| Interactive tutorial with tree visualization that has helped
| co-workers: https://learngitbranching.js.org/
| alextingle wrote:
| Thank you for posting that!
| paulddraper wrote:
| What the average amount of time until something goes wrong that
| can't be fixed in the UI?
| sksrbWgbfK wrote:
| For me, once a year and I have to use the reflog. But using a
| GUI is so much faster and safer that I won't change.
| Mercurial and Jujutsu have good command-lines, why can't git
| do the same?
| OkayPhysicist wrote:
| In more than one team I've been on over the years, I was the
| only person with a deep understanding of Git. What I've found
| as a result of being the "oh shit git" guy is that
|
| 1) all UIs are completely missing at least some of Git CLI's
| functionality (shoutout to git's most neglected feature, git
| notes)
|
| 2) all UIs have at least a couple git features so tucked away
| that you'll only find them if you know to look for them (git
| checkout -- path > temp_file is a common culprit here, but
| I've seen UIs that hide git ammend)
|
| 3) the average time for a UI-exclusive user to need my help
| for one of those two reasons was about a month.
| megak1d wrote:
| Came here to say the same - fork.dev is awesome.
|
| I used to be a CLI git guy but haven't used it in years now
| qalmakka wrote:
| GUI git clients are amazing in the hands of expert users, but
| terrible for any newcomer that has to actually use Git (and
| it's not like a designer checking out the source once or twice
| a month).
|
| The gripe I have is that unless you expose people to CLIs early
| on, they will just not learn how to use a CLI at all. Whenever
| something inevitably breaks badly due to GUIs abstracting away
| how git really works in favour of a nicer UX, they'll end up
| asking someone that know Git how to fix their mess. And then,
| it's too late - they already know how to be productive-ish with
| git and how to deliver something. They can't justify investing
| time into learning the CLI (especially if they're not that
| great with Powershell or UNIX shells) so they constantly keep
| leaning on a colleague instead of learning.
|
| This is not an hypothetical scenario - this really happened
| regularly at a place I worked at. Innumerable internal training
| lessons on Git went wasted due to people forgetting everything
| immediately by using Fork instead of the shell, and then
| pestering a handful of senior devs. Once IT banned Fork people
| were forced to use the terminal more often, so they had to
| learn how to use git for good and actually retained that
| knowledge via muscle memory.
|
| The adage I've learnt over the course of the years is that the
| majority of people will go to any length to avoid learning new
| stuff. It's mentally less tiring to either waste their time
| doing stuff in an unproductive way than learning new things.
| IMHO it's better to force people to learn stuff the "right way"
| early on than let them pick up bad habits and then having to
| correct them later.
| franky47 wrote:
| One of the beauties of Git is that as long as you've created an
| object, it's impossible to lose that work (short of nuking the
| .git directory).
|
| Committing often is key. Precommit hooks (that take more than
| ~100ms) go against that.
| ge96 wrote:
| I have had git corruption problems on a raspberry pi sd card,
| usually I just had to reclone/abandon that folder
| stephen_g wrote:
| It honestly sounds like git is the least of your problems
| here...
| extraduder_ire wrote:
| If you orphan the object by not having anything point to it, it
| goes away when "git gc" is run. That happens automatically
| after about two weeks by default.
|
| Even things like "git add" will create objects stored in the
| .git folder.
| amelius wrote:
| This is why I run Git inside Git, as the latter allows me to undo
| anything I do within the former.
| CharlesW wrote:
| As a Gitginner I'm wondering if this a good joke that went
| "wooooosh", or if this has something to do with submodules,
| or...?
| shuntress wrote:
| Git manages pretty much everything by using the `.git` folder
| created by `git init` and there is (as far as I am aware)
| nothing stopping you from going into that .git folder and
| running init again there to start using git to manage the
| internal state of your repository. At least... that is what I
| assumed the joke was.
| deadbunny wrote:
| Literally `git reflog`
| javier_e06 wrote:
| Lately I've been asked to avoid merge-commits. They pollute the
| logs? If my push is blocked I am too far behind I create a new
| temp branch of master and do a "merge --squash" to it and then a
| "reset --hard" from temp branch back to my original branch. Heck
| sometimes I rather keep my changes in patches to void does darn
| merge CONFLICTS...specially when rebasing.
| a_t48 wrote:
| From memory... git merge origin/master
| git reset origin/master git commit -am "squash" # might
| need some extra fixup if your branch has added files
|
| No need to make a temp branch. I know there's probably a more
| efficient way of doing this, but this is what's stuck in my
| head.
| pitaj wrote:
| Hard to understand exactly what your issue is here. Typically
| when people say "avoid merge commits" they mean they want you
| to almost always rebase instead of merge. Can you give an
| example or something?
| nuancebydefault wrote:
| The thing is if you merge immediately into master and have
| conflicts, you solve the conflict and only then you can merge.
| But then the conflict resolution sits at the merge point with a
| weird default commit message and is hard to decipher.
|
| A nicer way is merge master into your branch, with the rebase
| option (you can set that option as the default). This will put
| your changes on top of the master changes that happened during
| populating your own branch. There you solve any conflicts and
| those usually immediately show you what happened in the
| meantime, making it easier to do so. The latest greatest now
| sits in your branch.
|
| Then as a plus, you can retest that merge and if necessary, fix
| the merge.
|
| Optionally you can do a pull request for reviewing. The diff
| the reviewers see is conflict-less and makes sense, has only
| your changes.
|
| Then simply merge to master, which should be trivial if you
| don't wait for long.
| Nullabillity wrote:
| Merge main into your branch, then merge --no-ff your branch
| into main. No need to rebase or squash anything.
| Izkata wrote:
| > Merge main into your branch
|
| The same problem GP was trying to avoid is created here,
| the merge conflict resolution being on the merge commit.
| WorldMaker wrote:
| I think that people that think merge commits "pollute the logs"
| are missing key git features such as `--first-parent`. Git is
| natively a _graph_. It gets a lot of powers from that. If you
| don 't want to see all the details of the "subway diagram", add
| `--first-parent` as a default and focus on the higher level.
| Merge commits help avoid later conflicts by _saving_ how
| earlier conflicts were solved. Three-way merging in general and
| many of git 's more complex merging strategies all work
| _better_ if you save the merge commits. Rebasing throws that
| baby of information out with the bath water. (It 's also useful
| information to have as a developer needing to archeology dive
| for _how_ a regression happened. With a merge commit you can
| see the fingerprints of a bad merge or a mistake that wasn 't
| caught in an ugly merge. With a rebase or squash that
| information is gone, you have no idea where to find the bad or
| ugly merges, that data is swept under the rug.)
| Nullabillity wrote:
| On top of this, integration is an "interesting" step on its
| own! When trying to diagnose an issue it can be super
| valuable to be able to understand whether it was broken from
| the start or broken by the merge. Rebasing throws all of that
| valuable information away!
| daitangio wrote:
| I love this site, it helped me and it also funny. Kudos to the
| creator!
| bitwrangler wrote:
| Other fun git hacks...
|
| * https://hackaday.com/2017/05/23/stupid-git-tricks/
|
| * https://ongardie.net/blog/sqlite-in-git/
| grokx wrote:
| I can also recommend git flight rules:
| https://github.com/k88hudson/git-flight-rules
|
| It saved my work a couple of times.
| mfashby wrote:
| Related, you can get this as a nice printed zine
| https://jvns.ca/blog/2018/10/27/new-zine--oh-shit--git-/
| frakt0x90 wrote:
| I'm not proud of it, but my #1 "Oh shit" git operation is to just
| delete my local repo, reclone, and reapply the changes. Works
| really well for me 95% of the time. The rest I ask dev ops guy to
| help.
| wruza wrote:
| This should be a built-in git unshit
|
| Or git add --unshit -f ~HEAD^^
|
| If you're using git version <= 2.844.
| maleldil wrote:
| Jujutsu has `jj undo`, but which undoes whatever was your
| last jj command, regardless of what it was. It makes much
| more confident to do an operation I'm uncertain of. And if I
| regret something many actions down the line, you have `jj op
| log` (a better reflog).
| zahlman wrote:
| If you `jj undo` a second time, does it redo (undoing the
| undo), or does it back up another step?
| steveklabnik wrote:
| It redos, there's discussion about if and how this should
| change: https://github.com/jj-vcs/jj/issues/3700
| blharr wrote:
| Such a simple operation, but it'd probably fix 95% of
| problems I've had with git.
|
| "Uh oh, I tried to checkout a branch from remote by doing
| `git checkout origin/some-branch` instead of `git checkout
| some-branch` and made a couple source changes. Now I'm in
| detached head state. What is detached head ? I have to
| stash my revisions? Can I make a new branch with the same
| name or do I need to delete the origin/some-branch that I'm
| on?"
|
| When you could be able to just revert the "operation" and
| check out the correct branch, that's amazing.
| spokaneplumb wrote:
| I've been using Git for almost 15 years, and have _twice_ built
| programs /products that use Git internally to achieve certain
| results (that is, the program/product itself uses Git for
| things, not just using Git to manage the source code for the
| program/product) and... sometimes before doing something a
| little gnarly in Git I'll still just do "cp -R .git ../git-
| backup" or something like that, so I can replace my entire .git
| dir with an older copy if I screw it up too bad. It's a ton
| faster than figuring out the right way to un-fuck any
| particular operation or set of operations.
| fragmede wrote:
| Reflog is your friend. git break-my-shit
| git reflog ... output saying where you were
| before things broke ... grab the good commit sha
| git reset --hard good_commit_sha_from_reflog
| compiler-guy wrote:
| And yet up above we have others recommending to never,
| ever, use `git reset --hard ...`.
| psyclobe wrote:
| The same people probably want to ban knives!
| spokaneplumb wrote:
| The copy-the-.git-dir trick works for worse issues than can
| be solved with a single reset --hard. Damn near anything,
| really, as long as you haven't touched any remotes. It also
| works if you don't remember/understand how you broke it,
| where it's broken, or which state you need to try to reset
| to.
| guenthert wrote:
| You're not alone. https://xkcd.com/1597/
| philipwhiuk wrote:
| My hot take is that Git isn't nearly as hard as the endless blogs
| pretend.
| reaperducer wrote:
| Git is a technology that was invented to simplify things that
| ended up getting so complex over time that an entire industry
| started up around it to try to make it simple again.
|
| See also: Docker. Probably lots of others.
| globular-toast wrote:
| Actually, no. Git was a technology invented specifically to
| enable Linux kernel development. It hasn't become any more
| complex since its inception. The problem is most people
| aren't doing kernel development and have absolutely no idea
| what a distributed version control system is, yet they use
| git, a distributed version control system. I have no idea why
| we use it, to be honest, but I'm very glad that we do because
| the previous options were crap. Perhaps Mercurial is better,
| but git is good enough.
| adamc wrote:
| We were using svn before Git and easy cloning (and then
| PRs) has solved a LOT of problems. There are definitely
| still some things left to improve, though.
| tester756 wrote:
| "hard"? it is not hard, it is just poorly designed, the API
| (commands) are really terrible.
|
| Think of it: one person who cares about UX decades ago could
| make git 10 times more sane for milions of devs.
| jeppester wrote:
| I'm happy I didn't have to scroll too far to see this.
|
| Git's CLI isn't elegant, but it really isn't that big of a deal
| if you understand the basics of what a commit is, what a branch
| is etc.
|
| I struggle to understand why so many devs decide to treat it
| like mysterious arcane sorcery instead of just spending the
| needed time on learning how it works.
|
| The same can be said about regexes.
|
| Regexes and git are probably the two tools which I have
| benefitted the most from learning compared to how little time
| I've spend on learning them - and I wouldn't even consider
| myself an expert on either.
| tester756 wrote:
| >I struggle to understand why so many devs decide to treat it
| like mysterious arcane sorcery instead of just spending the
| needed time on learning how it works.
|
| For example: you have bazilion ways to achieve the same
| thing, all of them having its own quirks/advantages?
|
| It is just poorly designed, that's it, lol.
|
| I like to joke that if somebody else invented Git, then it'd
| be 10% less powerful, but 10 times more user-friendly
| stephen_g wrote:
| But any software evolves over time so if it had fewer ways
| of doing things in the past, it would very likely
| eventually pick them up because people have use cases for
| the advanced features.
|
| It's like complaining about languages ("English is hard to
| spell and doesn't have consistent pronunciation" etc.),
| they're constantly changing and that kind of thing is going
| to happen eventually...
| marssaxman wrote:
| > it really isn't that big of a deal if you understand the
| basics of what a commit is, what a branch is etc.
|
| Yes, that's what people mean when they say that git is hard.
| Instead of presenting you with an interface expressed in
| terms of the domain you intend to work in, whose commands
| represent the tasks you intend to perform, git dumps its guts
| all over the place and requires each user to re-implement the
| interface between "what you want to do" and "how git is
| built" inside their own brains instead. Once you have written
| git's missing user interface in your brain, you are fine; but
| that's a lot of work which is not necessary with other
| version-control systems.
| ioncannon wrote:
| Hey I worked with the person who made this! She did a fun
| presentation for our company.
| codazoda wrote:
| Is this related to "Oh Shit, git?" by Julia Evans?
|
| https://wizardzines.com/zines/oh-shit-git/
|
| Perhaps not and the authors just named it the same because it
| rolls off the tongue nicely.
| jvns wrote:
| Yes! Katie and I made it into a zine because I was such a huge
| fan of her work on https://ohshitgit.com/. (you'll notice she's
| a coauthor of the zine)
| globular-toast wrote:
| The one thing I wish people would internalise about git is _it 's
| an append only data store_. To get work into the store, you
| commit it. Once in the store there is not a command in git that
| can remove it.
|
| This is how the reflog works. Whatever you do, you can get back
| to a previous branch state and restore the work from the data
| store.
|
| But git can't help you if you don't commit. So just commit.
| Commit all the time. If you think it's too much overhead and you
| always forget to commit, fix your tools. If you're writing code
| all day you should be committing at a minimum every hour, in
| general.
| phtrivier wrote:
| This will feel very weird in April 2025, when we celebrate the
| 20th anniversary of git.
|
| I was there. And at some point I wondered if I should learn git,
| darcs, or bazaar, to replace SVN or CVS. Or did I try mercurial
| too ?
|
| I wonder if the "GitHub" effect has basically killed the need for
| a newcomer in the space of VCS. Maybe at some point, the yak is
| shaved enough ?
| jimbob45 wrote:
| SVN has always worked for me. You don't have to "teach" people
| SVN because it's intuitive and works just fine for the 99%
| case. I wish we would all stop larping as 1337 hackerz and just
| admit that git is overkill for the vast majority of people.
| dasil003 wrote:
| svn is perfectly fine and intuitive as long as you never want
| to branch and merge
| bear8642 wrote:
| huh?
|
| Svn can branch and merge - maybe bit more clunky but still
| works
| grandiego wrote:
| I agree with your sentiment. I was kind of "forced" to use
| (and eventually fully migrate to) git because the IDE
| integration to SVN became more quirky every year. Instead,
| git is already integrated in IDEs these days.
| WorldMaker wrote:
| Starting a new repo in SVN is find a server somewhere, if
| doesn't have SVN install SVN, if it does have SVN deal with
| whatever politics runs its trunk to find space/define a
| branch structure for you, and so forth.
|
| It is its own footgun as well, but with git you can git init
| any directory you want and have a repo. Other than the
| learning curve of the not particularly well tuned CLI (and
| there are all sorts of graphical clients today and
| alternative CLI clients), it's very low barrier to entry to
| get something/anything in source control.
|
| It's not just "larping as leet hackerz", there are real
| benefits to git over SVN. There are fewer barriers to entry
| for small teams and hobby devs, especially in a world with
| GitHub/GitLab/Sourcehut/and more, but also in the world where
| maybe a git repo never syncs with any other single machine or
| is hosted on the barest feature set SAMBA folder or is only
| ever using email-based PR flows.
|
| git could be easier to teach. git could have a better out of
| the box CLI. That doesn't mean "git is overkill" especially
| from the point of view of "needing a whole central server
| setup just to store multiple versions of a file is overkill".
| Git is perhaps "underkill", it does the bare minimum as best
| it can in whatever environment you give it. It's
| intentionally dumb and stupid (hence its name, to be fair)
| and it's learning curve is as much because it is "too dumb"
| than because it "isn't intuitive". I've seen some "intuitive"
| UIs built on top of it. Another comment here remarked "git
| isn't a source control system, it's a low level toolkit for
| building your own" and that's not far from the truth and
| definitely not far from git's origins (and its name). That's
| a sort of "underkill". ("One day we'll finally build the
| right, intuitive high level API." That's basically how git
| was designed. You don't have to just take my word on that,
| you can search the old mailing lists for all sorts of
| interesting discussions and debates on "porcelain" options.)
| zahlman wrote:
| >Starting a new repo in SVN is find a server somewhere, if
| doesn't have SVN install SVN, if it does have SVN deal with
| whatever politics runs its trunk to find space/define a
| branch structure for you, and so forth.
|
| Many years ago, SVN worked fine for me for single-user
| projects. I just made my own desktop be the server. But I
| wasn't publishing my code back then (it's not as if I would
| have have any effective way to tell people about it
| anyway). Now I have no idea how the equivalent of "pushing
| to origin" would have worked.
| WorldMaker wrote:
| Around the period I might have adopted SVN I recall it
| was a huge pain, if not impossible, to install on a
| Windows desktop; I tried multiple times, failed at each
| attempt, and eventually gave up. I was also in some labs
| at the time where we weren't allowed RDP to personal
| machines or services, or the lab machines just weren't
| great at it, or both (depending on the exact type of lab
| class and how worried the professor was of plagiarism),
| and mostly only had access to dumb sftp systems during
| the labs. That's when I discovered and fell in love with
| darcs. Distributed source control is great. Source
| control that you can push changes to/from the dumbest
| file systems is a super power. (Just the other year,
| even, I was using git and a dumb folder share to move
| source control changes to and from a VM that was
| firewalled from any network traffic because it had to
| be.) I miss some of the smarts of darcs still somewhat
| regularly having adjusted to this timeline where git won
| handily, but I'm not going back to a centralized source
| control system and git is "good enough" most of the time.
| Rexxar wrote:
| You can create a repo in a directory and use the local
| path in svn url without using any service or server
| process since the beginning of SVN.
|
| You can even do it on shared directory for a small team
| even it's not recommended if there is a lot of concurrent
| users.
| zahlman wrote:
| I just used the TortoiseSVN installer on a couple
| different machines and I recall it being perfectly smooth
| each time.
| mardifoufs wrote:
| SVN is more alien to me than git. Does that make you a
| LARPing epic hacker?
| krick wrote:
| Working with SVN was terribly slow on any decent size
| codebase.
| hiAndrewQuinn wrote:
| Clearly you have never needed code search across 50+ SVN
| repositories before, then. ;)
|
| No, but seriously, I wrote https://andrew-
| quinn.me/reposurgeon for a reason. While I actually see some
| big benefits to SVN over git for areas with large binary
| assets like game development, the tool is just so ancient
| these days that it's just easier for me to convert SVN repos
| to git repos and then use those to figure out what I actually
| need to do. It feels a lot like working with Laplace
| transforms, translating and un-translating between two not
| quite equal ways of measuring reality.
|
| That's not even considering that the kinds of companies still
| using SVN in 2025 tend to have a lot of code to wade through.
| Serious selection effects in play there -- mostly for good,
| to be clear.
| steveklabnik wrote:
| The GitHub effect is real, like all network effects, but that
| doesn't mean improvement is impossible. I've switched entirely
| to jj, and it having git compatibility means that I don't need
| to rely on anyone else to make that happen.
|
| I am growing increasingly frustrated with various aspects of
| GitHub, and so I hope someday we all move past it too, but I
| don't think there's as simple of a path forward there.
| paulddraper wrote:
| Any improvement will have to be git compatible at the very
| least, e.g. jj.
| acombandrew wrote:
| this is good but is extremely reddit
| julienb_sea wrote:
| Oh shit, I accidentally `git reset HEAD~1` and moved the last
| commit to file diffs, which was a merge to master, and my file
| diff now is both the last branch merge and everything I've done
| in the last 8hrs. I did this once and it was a gigantic PITA to
| undo, if anyone has any hot tips for that particular idiocy...
| Am4TIfIsER0ppos wrote:
| `git reset` again to move to the right commit
| bradhe wrote:
| Love that the very first thing mentions reflog, arguably the most
| confusing and complicated git feature.
|
| The rest are good though.
| argentinian wrote:
| I believe I have a good mental model of what git does, but I
| never remember commands' arguments to use when they are
| moderately complex. I mean that the commands are not discoverable
| or easy to memorize.
|
| I don't know if that's because the text UI is bad, or because
| it's simply difficult to explain with text what to do to
| manipulate a tree.
| stackghost wrote:
| Both.
|
| Manipulating complex trees via text is not easy, but the text
| UI is objectively bad:
|
| https://stevelosh.com/blog/2013/04/git-koans/
| gootz wrote:
| Pro tip: Sometimes it's easier to rewrite you're entire app
| rather than wrestle with git commands. /s
| GianFabien wrote:
| Reading these tips confirms that I'm too stoopid to use git.
|
| Fortunately, I don't have to use git. So I just store work-in-
| progress as time-stamped files. Storage is cheap and plentiful.
| Can always diff, cherry pick, etc without confusing myself.
| dgfitz wrote:
| I'm pumped a search for hg+mercurial had hits in this thread. I
| am and will continue to be completely blown that hg lost the dvcs
| wars. It's a better tool.
| gmueckl wrote:
| It _is_ the unquestioningly better tool right now. It 's
| available, stable, battle-tested and it's actively supported.
| It's a case of "being the change you want to see". Just use it.
| Claims that it lost are counterproductive. The implicit
| deterrence from those statements is what is actively keeping
| Mercurial's adoption low.
|
| Hosting is available at least from Sourcehut and heptapod.host.
|
| I'm running a private Heptapod instance (Gitlab fork with
| direct Mercurial support). It just works.
| greazy wrote:
| Are there any public forges that support hg?
| gmueckl wrote:
| Have a look at heptapost.host for paid hosting and
| foss.heptapod.net for free public hosting for OSS. Is that
| what you are looking for?
| romaniitedomum wrote:
| > Are there any public forges that support hg?
|
| Sourceforge, Sourcehut, and GNU Savannah all support
| Mercurial.
| paulddraper wrote:
| It's the slower tool.
| guenthert wrote:
| That was relevant to Linus in the early 2000s, but then, we
| didn't have NVMe SSDs.
| thatsthejoke wrote:
| That sounds interesting. Does anyone have a GitHub link?
| jaitaiwan wrote:
| I swear there used to be a choose your own adventure version of
| this where you could answer questions about what you did wrong
| and get a step-by-step "here's what to do" after.
| zargon wrote:
| Perhaps it was this one?
| https://sethrobertson.github.io/GitFixUm/fixup.html
| felipeerias wrote:
| For a developer, one of the most useful things that LLMs can do
| is help out with Git issues.
|
| It really says something about the design and documentation of a
| tool when you need a (far more complex and energy-intensive)
| Artificial Intelligence to be able to use it without making too
| many mistakes.
| margaretdouglas wrote:
| I force pushed over origin/master from a very not-up-to-date
| feature branch and don't have the remote history I overwrote
| fetched locally.
| sagarpatil wrote:
| I just use cursor agent to do git now (unless it's simple stuff)
| sundarurfriend wrote:
| Silly comment, but:
|
| Every time I see `git reflog`, I see it as re-flog. It's possible
| that's even the reason I never remember the command, I
| subconsciously can't bring myself to think of it as "reference
| log". Instead, it's asking git to sell something cheaply,
| _again_.
| yonatan8070 wrote:
| I have that with fstab
| kmoser wrote:
| > Only amend commits that only exist in your local copy or you're
| gonna have a bad time.
|
| "Gonna have a bad time?" I really wish things like this were
| explained in more detail, rather than with glib warnings that are
| unhelpful unless you already know what they mean.
| extraduder_ire wrote:
| The commit you're amending doesn't exist on your copy anymore,
| despite existing on the remote that you've pushed to.
|
| Warnings about detaching the HEAD in git are so common that
| they're kind of assumed to be basic knowledge to a lot of
| people. Explaining why it's bad if you don't already know would
| take quite a while too.
|
| I do wish git had some form of warning before you rewrite
| history that's been pushed somewhere. It should already have
| all the data to know that.
| upghost wrote:
| Before learning magit on emacs, this site saved my ass so many
| times. After learning magit on emacs, this site saved my ass so
| many times.
| blharr wrote:
| It used to save my ass a lot. It still does, but it used to,
| too.
| meinersbur wrote:
| Avoid `git reset --hard` and `git clean -xfd`. To get a clean
| working-tree, use `git stash --all`. Allows restoring files if
| necessary. Saved my sorry bottom multiple times.
| user4511 wrote:
| Oh how I wish more devs would just read the documentation for the
| tools they pick. I read the git documentation end-to-end. Never
| really had any issues with it and most commands feels natural to
| use.
| blharr wrote:
| If you memorize the documentation I suppose there's no problem
| with it, but even then there's confusing things from the
| beginning design approach.
|
| Like, reset vs revert vs restore, using three similar starting
| synonyms for different operations.
|
| Reset is particularly confusing because it sounds incredibly
| destructive, but if you do a soft 'git reset', it just moves
| the "changes to be committed" to be not staged for the commit.
|
| Then, if you change a single flag (--hard) it is destructive,
| instead erasing all those changes from your disk.
|
| And there's a reason nobody reads the docs, because they're
| laid out confusingly at first glance to an unfamiliar person.
|
| If I go to git-scm.com, click docs, the first suggestion is the
| reference manual. The first guide is on "gitattributes" which
| gives no philosophy or context as to what it is even used for.
| Ok, maybe, I'll just check the complete list of git commands...
| and it starts talking about porcelain and plumbing. Nope, thats
| not what I need. Maybe try the link "git" under Setup and
| Config. There the description finally links to a useful
| "gittutorial" page.
|
| The gittutorial even has some confusing or specific terminology
| that makes git seem hard. From the beginning of importing a new
| project "Assume you have a tarball project.tar.gz with your
| initial work"... why do we need to refer to tar at all, and it
| doesn't even do the credit of explaining the tar xzf command or
| what that tarball is. It could easily say 'assume you have a
| directory', which is the more common case and be 200% more
| simple.
| scudsworth wrote:
| 8 years of posting this
___________________________________________________________________
(page generated 2025-01-17 23:02 UTC)