Yeah learned this the hard way.

top 95 comments

sorted by: hot top controversial new old
[–] 136 points 1 year ago (33 children)

I've had juniors who didn't believe this, so just to say it: If you know what you're doing, practically any Git problem is recoverable.

The one major exception is if you delete your local changes before committing them.

  • source
  • hideshow 33 child comments
  • [–] 48 points 1 year ago (21 children)

    Yeah.But many of them are extremely annoying. Specifically screwing up rebase. It is recoverable, but very annoying.

    That said I have seen juniors make two other common mistakes.

    1. Pushing your commit without fetching
    2. Continuing on a branch even after it was merged.

    I'm fed up with these two. Yesterday I had to cherry-pick to solve a combination of these two.

  • source
  • parent
  • hideshow 21 child comments
  • [–] 39 points 1 year ago* (last edited 1 year ago) (9 children)

    Maybe I'm just a wizard, or I don't know what y'all are talking about, but rebases aren't special. If you use git reflog it just tells you where you used to be before the rebase. You don't have to fix anything, git is append only. See where the rebase started in reflog, it'll say rebase in the log line, then git reset --hard THAT_HASH

    Pushing without fetching should be an error. So either they got the error, didn't think about it, and then force pushed, or someone taught them to just always force push. In either case the problem is the force part, the tool is built to prevent this by default.

    Continuing after merge should be pretty easy? I'd assume rebase just does it? Unless the merge was a squash merge or rebase merge. Then yeah, slightly annoying, but still mostly git rebase -i and then delete lines look like they were already merged?

  • source
  • parent
  • hideshow 9 child comments
  • [–] 19 points 1 year ago (2 children)

    See all this is fine for someone with good experience in git. They know how to solve the screw up. But wih junior devs, who don't know much about it, they will just get confused and stuck. And one of the senior has to involve and help them solve. This is just annoying because these can be avoided very easily. Until they understand the pattern of how everyone operates with git, it just creates issues.

    To me first time causing this issue is completely fine. I will personally sit with them and explain then what went wrong and how to recover. Most of them will repeat it again, act clueless and talk like they are seeing this for the first time in their life. That is the difficult part to me.

    May be I'm just old school, and a grumpy old person, even though I'm not that aged.

  • source
  • parent
  • hideshow 2 child comments
  • [–] 3 points 1 year ago

    Sounds like the onboarding process needs to have a step in it that says "here's a link to a git tutorial, read this and get familiar with using git, as it's an integral tool that you will use every single day on the job". Bonus points for providing a sample repo that juniors can use to mess around with git, extra bonus points for including steps in the onboarding materials for the juniors to set up their own repos to play around with.

  • source
  • parent
  • [–] 4 points 1 year ago (4 children)

    Same… My usual strategy: rebase, if conflict abort and merge, if no conflict continue; merge always with explicit commits to master / main (no fucking squashing); keep task references in branch names and commit messages.

  • source
  • parent
  • hideshow 4 child comments
  • [–] 1 point 1 year ago (3 children)

    Same, but typically I will just resolve the conflicts during the rebase. Makes for cleaner commit history. Merge commits are for combining multiple big unrelated pieces of work together, where rebasing would be too annoying (let's say 100s of commits each).

  • source
  • parent
  • hideshow 3 child comments
  • [–] 1 point 1 year ago* (2 children)

    In my cases I has to solve same code conflicts multiple times during a rebase, so I just don't try them when hit with conflicts.

    I fail to see the benefits of "clean" git history

  • source
  • parent
  • hideshow 2 child comments
  • [–] 1 point 1 year ago (1 child)

    In my cases I has to solve same code conflicts multiple times during a rebase, so I just don’t try them when hit with conflicts.

    Yeah if you have two branches, both with a bunch of commits which all modify the same areas of code, and reordering the commits doesn't help, I can see how it is easier to merge.

    I fail to see the benefits of “clean” git history

    Well, if the commit history is clean and mostly linear, it's much easier to read, understand and review. git blame will also be much nicer which is really important for debugging big codebases. Of course it's a tradeoff, as usual.

  • source
  • parent
  • hideshow 1 child comment
  • [–] 2 points 1 year ago

    Continuing on a squash merged branch is very annoying, and I had to deal with this in one repo regularly... Luckily I was annoyed enough to research about this and found out about rebase --onto "main merge commit" "branch merged commit".

  • source
  • parent
  • [–] 3 points 1 year ago (6 children)

    Is it ok to continue on a branch if you also merge back main into it? Like, branch gets merged into main on remote, local main pull, local merge main into local branch, push branch?

  • source
  • parent
  • hideshow 6 child comments
  • [–] 6 points 1 year ago* (3 children)

    So this workflow is needed if you are working on a public, i.e. multiple devs collaborating on a single branch, scenario. But it is much better to avoid this as much as possible. Usually it is a 'scoping' issue, where you create a branch that is too broad. For example 'api-for-frontend', which is a massive thing.

    But let us say you absolutely have to get multiple devs on same branch, then this workflow is totally fine. There is nothing wrong in it.

    In our org we prefer to delete the branch after merge. In a way it says 'this branch is closed'. This is to encourage devs to define smaller and more logically scoped branches.

    I want to take this opportunity to say that, branch is just a label on a commit, with some additional functions. Once you start focus on commits and lineage of the commits, then branches become some what irrelevant.

  • source
  • parent
  • hideshow 3 child comments
  • [–] 2 points 1 year ago (2 children)

    Aha. I was part of a project where each dev had their own long running branch for non-specific work and this was the norm, but it always felt clunky. And often resulted in merge issues.

  • source
  • parent
  • hideshow 2 child comments
  • [–] 4 points 1 year ago* (last edited 1 year ago) (1 child)

    Is it ok to continue on a branch if you also merge back main into it?

    On some repositories, sure.

    But better maintained repositories don't allow merge commits (because merge commits suck), and so will have squashed (or rebased) on merge.

    (If squashed) The squash will have changed commit IDs, so a long running branch rebased won't benefit from a clean shared commit history.

    So it can work, but "you're gonna have a bad time."

    In general, git works best if branches are thrown away as soon and as often as possible.

    (Edit: Good clarification in response below, added here for consistency and accuracy.)

  • source
  • parent
  • hideshow 1 child comment
  • [–] 4 points 1 year ago

    You don't have to squash to avoid merge commits. Instead, you can git rebase main to update your branch. Effectively, this will rewrite the history of your branch, as if you had just branched from the main-branch and then instantly coded all your changes on top of that. (Well, the commit timestamps won't change, but they will sit on top of the changes of the main-branch.)

    Afterwards, you should be able to merge into main by switching to it and then running git merge --ff-only your_branch.
    Because all the changes sit on top of the main-branch commits, it should be able to fast-forward. No actual merging needs to take place then. You've already resolved any conflicts while rebasing.

    This also allows you to keep branches for longer, so long as you frequently rebase and merge back.

  • source
  • parent
  • [–] 3 points 1 year ago* (1 child)

    Specifically screwing up rebase. It is recoverable, but very annoying.

    WDYM? Typically git rebase --abort will "just work". If you have specifically done something really wrong, just look into git reflog and then git reset --hard to whatever commit you were before the rebase.

    Pushing your commit without fetching

    Git won't allow you to do that if you set up your server properly. It will force you to pull first. I have [pull] rebase = true in my settings so that it always rebases my commits instead of merging them, which makes for much cleaner history.

    Continuing on a branch even after it was merged.

    This generally shouldn't be a problem, you can just rebase the branch afterwards and it will be fine (the common commits will typically just be dropped).

  • source
  • parent
  • hideshow 1 child comment
  • [–] 1 point 1 year ago

    The problem is not when I have to rebase. I know how to handle it. But with juniors they approach us only when things are in a really bad situation, where they cluelessly applied some commands they found on internet or from an LLM. Then it is very annoying to sit down and untangle the mess they created.

    And regarding the pushing without fetching, it is usually a different branch. So they won't incorporate the new changes in the main branch into their working branch, but just push their work into a branch. Again not a big deal. Just annoying.

  • source
  • parent
  • [–] 0 points 1 year ago (1 child)

    I’ll get chastised, but when I screw up a rebase I create a backup branch and then have an LLM do the fixing…

    I’m not proud of it, but I’m a lazy man who doesn’t want to resolve the same conflict 32 times.

  • source
  • parent
  • hideshow 1 child comment
  • [–] 9 points 1 year ago

    Having to resolve the same conflict multiple times suggests excess noise in your git history. You might want to pay closer attention to creating a useful git history. It’ll help with any future archaeology, and it’ll also help rebasing go smoothly.

  • source
  • parent
  • [–] 4 points 1 year ago (3 children)

    Does deleting the repo off disk and redownloading from remote considered recovering? If so I'm a git expert.

  • source
  • parent
  • hideshow 3 child comments
  • [–] 5 points 1 year ago (2 children)

    Delete? Never.

    mv git_repo git_repo.bad
    
  • source
  • parent
  • hideshow 2 child comments
  • [–] 3 points 1 year ago (2 children)

    I’ve even recovered from deleting local changes I forgot how but there is a way! (It’s not something to rely on but can help in a pinch!)

  • source
  • parent
  • hideshow 2 child comments
  • [–] 7 points 1 year ago (1 child)

    Well, if you did commit it, but just hadn't pushed it yet, and then somehow lost that commit, then git reflog would be the tool for it.
    Without a commit, sometimes you may have already staged some changes for an upcoming commit and can roll back to that.

    But if neither of those are the case, then I can't really imagine how Git should help you there. You haven't told Git about those changes yet, so it's out of scope.
    At that point, you better hope your editor's undo history goes back far enough...

  • source
  • parent
  • hideshow 1 child comment
  • [–] 2 points 1 year ago

    Fun fact! If you added a file but never committed it you can still recover it with git fsck --lost-and-found. The changes were still added to the git object store, and by grepping through the dangling blobs you can find the object containing the changes you care about.

  • source
  • parent
  • [–] 47 points 1 year ago (14 children)
  • [–] 4 points 1 year ago (3 children)
  • [–] 10 points 1 year ago (2 children)

    Rebase the comment chain and force push!

  • source
  • parent
  • hideshow 2 child comments
  • [–] 2 points 1 year ago (7 children)

    I hear people praise git reflog a lot, but when do y'all use this? Most I've ever needed is git log --graph for history checking. Maybe if I was in a situation where I knew the code on local branch X was working on Friday, but not anymore on Monday, then I could use git reflog to go back to Friday for that local branch right? Is that the idea?

  • source
  • parent
  • hideshow 7 child comments
  • [–] 13 points 1 year ago

    Power users rebase with squashes and fixups multiple times a day. Especially if the job’s integration process isn’t enforcing long living branches.

    Reflog is useful then, because you literally rewrite history every rebase.

  • source
  • parent
  • [–] 4 points 1 year ago

    I only use it when I've royally messed up and the commit I need to get back is no longer referenced anywhere. Accidentally deleted a branch, finished a merge or rebase before realizing I messed up, that kind of thing, just use the reflog to find it again, get a branch pointing to it, then try again.

  • source
  • parent
  • [–] 3 points 1 year ago*

    git log will only show you commits in your history. If you're only ever working forwards, this will contain all the stuff you'll ever need.

    But if you're rewriting history, like with a rebase or squash or something, or you're deleting branches without merging them, then you can run into a situation where the official history of your branch doesn't contain some of the commits that used to exist, and in fact still exist but are unlinked from anywhere. So reflog is the log of where you've been, even if where you've been isn't in the official history anymore, so you can find your way back to previous states even if there isn't otherwise a name for them.

    If all you care about is your current history, git can use the dates of commits just fine to see where you were on Thursday without needing the reflog.

  • source
  • parent
  • [–] 42 points 1 year ago* (7 children)
    1. Use git for any code you write. Yes, even a simple script.
    2. Commit and push often. More often than you think is reasonable. You can always rebase / fixup / squash / edit but you can't recover what you didn't commit.
    3. ???
    4. Profit.

    Seriously, once you commited something to the repo it's hard to lose it. Unless you delete .git. But a this point frequent pushing has your back.

    I know git can be hard to grasp in the beginning. It was hard for me too. I highly encourage everyone to put in the effort to understand it. But if you don't want to do that right now just use it. Just commit and push. It will pay off.

  • source
  • hideshow 7 child comments
  • [–] 8 points 1 year ago* (last edited 1 year ago) (5 children)
    1. (3) Get annoyed by constantly increasing Code Coverage Requirements on untestable (often legacy) code. Even afding comments requires code coverage go up! Line must always go up!
    2. Change step 2 to "Commit and push ONLY when absolutely necessary. Because adding comments often requires a rewrite of untestable code."
    3. Go back to Step 2 and wait for a major bug.
  • source
  • parent
  • hideshow 5 child comments
  • [–] 3 points 1 year ago* (2 children)

    Our company "architects" decided we needed 80% coverage minimum. On a mostly .Net 4.8 codebase. Hundreds of programs used in prod, with barely any tests in sight.
    It's a fucking nightmare.

  • source
  • parent
  • hideshow 2 child comments
  • [–] 2 points 1 year ago (1 child)

    Ah, the classical "just introduce tests in a legacy codebase", what can go wrong?

    My condolences, it's always a BITCH to handle

  • source
  • parent
  • hideshow 1 child comment
  • [–] 3 points 1 year ago

    Fixing that bug you just found in prod : half a day. Adding enough tests so the app is now at 80% coverage : a whole fucking week. My student colleague was not impressed. I was like "yup, that's what jobs are like".

  • source
  • parent
  • [–] 3 points 1 year ago*

    Why would you care about code coverage requirements on a branch that is currently in development? My work in progress commits might not build because they don't even compile, let alone have passing tests. The only time I care about the build passing and meeting requirements is when I'm ready to create the pull request.

    Also code coverage is a useless metric, but that's a different story.

  • source
  • parent
  • 3 is not related to using git in any way. I'm not really sure what you mean in 4. I didn't mean making a lot of changes, I meant that you should not wait with committing until you have a finished feature / fix / whatever. Commit after each refactor, commit after adding a new testable unit. It's always better to have more checkpoints. If your team does code review, they will appreciate atomic commits too.

  • source
  • parent
  • [–] 26 points 1 year ago (4 children)

    Special shout out to the person who committed a gigabyte memory dump a few years ago. Even with a shallow clone, it's pretty darn slow now.

    We can't rewrite history to remove it since other things rely on the commit IDs not changing.

    Oh well.

  • source
  • hideshow 4 child comments
  • [–] 9 points 1 year ago

    Sounds like a flawed workflow, if this didn't go through at least code review. Was it committed directly to master?

    Curious to know what kind of system relies on hashed not changing? Technically the hashes don't change, but a new set of commits is made. The history diverges, and you can still keep the old master if you need it for some time, even cherry pick patches to it..

  • source
  • parent
  • The guy at work who managed git before me, well didn't quite have the knowledge I do and was not using LFS. In one of the main repos a 200mb binary was pushed 80+ times. This is not the only file that this happened to. Even if you do a shallow clone, you still need to add the commit depth eventually. It's a nightmare.

  • source
  • parent
  • [–] 2 points 1 year ago

    Special shout out to the person who committed a gigabyte memory dump a few years ago. Even with a shallow clone, it's pretty darn slow now.

    If you want to be the team's hero, I've had good luck removing old commits using git filter repo.

    https://hibbard.eu/erase-sensitive-files-git-history-filter-repo/

    We can't rewrite history to remove it since other things rely on the commit IDs not changing.

    Oh right. Oof.

    I would be working to arrange an accident for those other things. Those other things probably need to be retired.

  • source
  • parent
  • [–] 26 points 1 year ago (1 child)

    You know... A version control system... That class of software that makes it possible for you to recover from any error you commit.

  • source
  • hideshow 1 child comment
  • [–] 24 points 1 year ago (6 children)

    With Jujutsu (which is compatible with git), you can just

    jj undo
    
  • source
  • hideshow 6 child comments
  • [–] 15 points 1 year ago* (last edited 1 year ago)

    Been using it for over a year now and not being scared of trying operations is such a boon. It helps so much with learning when you know you can just roll back to an earlier state.

    I've had zero issues with it so far and no one at work noticed anything different, other than there being a bit more rebase spam on PRs.

  • source
  • parent
  • [–] 7 points 1 year ago (2 children)

    That is so cool. Why doesn't git have this already?

  • source
  • parent
  • hideshow 2 child comments
  • [–] 1 point 1 year ago (1 child)
  • [–] 2 points 1 year ago

    Anything you can do in Jujitsu you can do in git.. The big difference is a paradime change:

    -instead of a working directory that has pending changes you need to add than commit, all changes are in a commit that is lacking metadata.

    The system has better "editing" of local history to set that meta data. But once you push to a shared repo you run the usual risks of force pushing.

    I'm not sold, rather git not do anything until asked and just run git status constantly but I don't have first hand experience.. I would theory it would be more likely to add a file you didn't mean to.. Unlike those who use windows guis for git and forget to add new files.

  • source
  • parent
  • [–] 19 points 1 year ago* (last edited 1 year ago) (10 children)

    Isn't it the exact opposite?

    I learned that you can never make a mistake if you aren't using git, or any other way for having access to old versions.

    With git it is really easy to get back to an old version, or bisect commits to figure out what exact change was the mistake.

    The only way I understand this joke is more about not wanting to be caught making a mistake, because that is pretty easy. In other methods figuring out who did the mistake might be impossible.

  • source
  • hideshow 10 child comments
  • [–] 13 points 1 year ago* (last edited 1 year ago) (4 children)

    This is not about mistakes in the Git-managed code. This is about mistakes in the Git commands themselves. Anything that involves merging/rebasing/conflict resolution can potentially be botched. These mistakes are usually fixable, but:

    1. Fixing it requires some Git proficiency behind the level of the common Git user.
    2. If you don't catch it in time, and only find the mistake when it's deep in your layers of Git history - well, good luck.
  • source
  • parent
  • hideshow 4 child comments
  • [–] 5 points 1 year ago

    Went to tech elevator boot camp, was a decent experience even if I don't find myself doing exactly what I was expecting to do. Life is that way though.

    Anyways, my first week I fucked some git stuff up so bad I became the go to guy when anyone had any git issues because I had to learn so much to undo my egregious error. I don't remember now exactly what it was but it took some serious git magic to sort.

    Just saying that point 1 is very true. And yeah don't make mistakes in git.

  • source
  • parent
  • [–] 1 point 1 year ago

    Short of manually deleting .git you can always find any commit, you can walk backwards through your reference lof if it comes to it, the only real risk is throwing out unstaged changes.

  • source
  • parent
  • [–] 0 points 1 year ago*

    Hmm... I am using git for maybe 15 years... Maybe I'm just too familiar with it... and have forgotten my initial struggles... To me using git comes natural... And I normally pay a lot of attention to every single commit, since I started working on patches for the Linux kernel. I often rebase and reorder commits many times, before pushing/merging them into a branch where continuity matters.

  • source
  • parent
  • [–] 2 points 1 year ago (4 children)

    You're confusing errors in your code, and errors while doing some git command you thought you knew. Lucky you, it's clearly never happened to you because you don't mess around with it.

  • source
  • parent
  • hideshow 4 child comments
  • [–] 1 point 1 year ago* (last edited 1 year ago) (3 children)

    Sure, I sometimes messed up with git, but a git reset , checkout, rebase or filter-branch (In the extreme cases) normally fixes it, but real issues are very rare. And I use git a lot... But only the CLI, maybe people have issues with GUIs?

  • source
  • parent
  • hideshow 3 child comments
  • [–] 7 points 1 year ago (2 children)
  • [–] 2 points 1 year ago

    Funny those are commands I avoid.. They all have to do with editing history which I know there is a vocal group here that loves "clean" history but that isn't what happened.

    sure merge full features so you can roll back a feature.. And if something is really off I might start from a snapshot commit and cherry pick/merge a bunch in but usually history is histoy.. If submitting to a public project I may make a new branch with the cleaned version but why edit in line. That is risking issues.

  • source
  • parent
  • [–] 31 points 1 year ago (7 children)

    Git repository operations are (almost?) always recoverable. git reflog is your friend.

    The filesystem operations are another story. Handle with care.

  • source
  • hideshow 7 child comments
  • [–] 7 points 1 year ago (6 children)
  • [–] 18 points 1 year ago (5 children)

    Think of it like your browser history but for Git. It’s a list of the SHAs related to your recent operations.

    And because Git is a content-addressable data store, a SHA is basically like a URL. Even if a branch no longer exists, if you know the SHA it pointed to then you can still check out the exact contents of that branch. The reflog helps you find that.

  • source
  • parent
  • hideshow 5 child comments
  • [–] 17 points 1 year ago (4 children)

    Goddamit... It's ref log, not re flog. I thought this was related to blame and never touched it lmao

  • source
  • parent
  • hideshow 4 child comments
  • [–] 3 points 1 year ago (2 children)

    Re flog is when your devs don't follow your guides and mess uo git history again.

  • source
  • parent
  • hideshow 2 child comments
  • [–] 2 points 1 year ago (1 child)

    I legit thought it was to publicly call out a user to be (metaphorically) flogged

    And while it's not how I do things, I totally understand the impulse. Tell me that doesn't sound like something that could exist

  • source
  • parent
  • hideshow 1 child comment
  • [–] 14 points 1 year ago

    I don't think you should be scared of git.

    Unless by "scared" you mean "I pasted from ChatGPT and now I don't know what to do," in which case, please be more scared.

  • source
  • [–] 5 points 1 year ago (1 child)

    We need version control for the version control.

  • source
  • hideshow 1 child comment
  • [–] 5 points 1 year ago

    git reflog is your friend

    The worst thing you could do is delete your local git repo.

  • source
  • [–] 9 points 1 year ago

    Skill issue

  • source
  • load more comments
    view more: next ›