Walk me through fixing this git thing



  • OK, so I checked out an old version of my project on purpose, basically because I want to wipe a bunch of commits out of existence. I fixed a whole bunch of bugs that should have been fixed before those spurious commits.

    A few questions:

    1. Git is telling me that I have a detached head. How do I make all the new commits end up in the right place?

    2. Ideally, I'd like to take a quick peek at the "bad" commits I'm deleting to see if there's anything I can salvage. I know there's some good work in there.

    What do I do?

    WHAT DO I DO?


  • sekret PM club

    @captain said in Walk me through fixing this git thing:

    Git is telling me that I have a detached head.

    0_1527194523946_9d9f606d-992e-4ea0-a646-6d1be345f1f7-image.png
    ❓


  • Trolleybus Mechanic

    In my opinion, don't try to monkey with the commit history. Just make your changes or reverts or whatever on top of those other commits.


  • Banned

    Detached head means the checked out commit isn't the top commit of any branch, and thus further commits won't be added to any branch, effectively making them temporary (safe for a couple days, but purged on next GC run). You can overwrite which commit a branch points to by checking out the branch and doing git reset --hard <commit hash>. You can make some commits on detached head and then reset, but it's safer to first reset and then make your commits. When you do the reset, the commits that used to be on branch but aren't anymore become detached and susceptible to GC. Remember that every time you commit, checkout, reset etc., all relevant commit hashes are recorded in git reflog so if you fuck up and accidentally delete wrong one, you can git reset --hard back to it.



  • @gąska said in Walk me through fixing this git thing:

    Detached head means the checked out commit isn't the top commit of any branch, and thus further commits won't be added to any branch, effectively making them temporary (safe for a couple days, but purged on next GC run). You can overwrite which commit a branch points to by checking out the branch and doing git reset --hard <commit hash>. You can make some commits on detached head and then reset, but it's safer to first reset and then make your commits. When you do the reset, the commits that used to be on branch but aren't anymore become detached and susceptible to GC. Remember that every time you commit, checkout, reset etc., all relevant commit hashes are recorded in git reflog so if you fuck up and accidentally delete wrong one, you can git reset --hard back to it.

    Side note: whenever I see git reflog, I think of the punishment inflicted on sailors back in the day, not a REFerence LOG.


  • Considered Harmful

    @e4tmyl33t said in Walk me through fixing this git thing:

    @captain said in Walk me through fixing this git thing:

    Git is telling me that I have a detached head.

    0_1527194523946_9d9f606d-992e-4ea0-a646-6d1be345f1f7-image.png
    ❓

    0_1527196154250_Ms_fortune_render.png ❓


  • Banned

    @benjamin-hall said in Walk me through fixing this git thing:

    @gąska said in Walk me through fixing this git thing:

    Detached head means the checked out commit isn't the top commit of any branch, and thus further commits won't be added to any branch, effectively making them temporary (safe for a couple days, but purged on next GC run). You can overwrite which commit a branch points to by checking out the branch and doing git reset --hard <commit hash>. You can make some commits on detached head and then reset, but it's safer to first reset and then make your commits. When you do the reset, the commits that used to be on branch but aren't anymore become detached and susceptible to GC. Remember that every time you commit, checkout, reset etc., all relevant commit hashes are recorded in git reflog so if you fuck up and accidentally delete wrong one, you can git reset --hard back to it.

    Side note: whenever I see git reflog, I think of the punishment inflicted on sailors back in the day, not a REFerence LOG.

    Whenever I use git reflog, it absolutely feels like a punishment.



  • @captain Disclaimer that I am by no means a Git expert in any way. Here's what I would have done:

    1. Pulled the specific older version of the code you're interested in
    2. Push it back up to a new branch while you work on it (this will prevent detached heads)
    3. Use your favorite GUI compare tool to compare the other commits 1 by 1 and see which you want to keep and which you don't
    4. When you find you want to keep one, you can "cherry pick" it into your branch
    5. When you're done, merge your branch back into the master using the "ours" option (which basically tells Git to override that branch with the one you're merging in-- it more or less changes the merge to an overwrite.)
    6. Not post weird anime drawings of characters removing their heads

  • Considered Harmful

    @blakeyrat said in Walk me through fixing this git thing:

    Not post weird anime drawings of characters removing their heads

    You just called Ms. Fortune anime? I'm appalled.


  • kills Dumbledore

    @benjamin-hall said in Walk me through fixing this git thing:

    @gąska said in Walk me through fixing this git thing:

    Detached head means the checked out commit isn't the top commit of any branch, and thus further commits won't be added to any branch, effectively making them temporary (safe for a couple days, but purged on next GC run). You can overwrite which commit a branch points to by checking out the branch and doing git reset --hard <commit hash>. You can make some commits on detached head and then reset, but it's safer to first reset and then make your commits. When you do the reset, the commits that used to be on branch but aren't anymore become detached and susceptible to GC. Remember that every time you commit, checkout, reset etc., all relevant commit hashes are recorded in git reflog so if you fuck up and accidentally delete wrong one, you can git reset --hard back to it.

    Side note: whenever I see git reflog, I think of the punishment inflicted on sailors back in the day, not a REFerence LOG.

    Until quite recently I genuinely thought it was re flog



  • @pie_flavor You're right, she's a cheap, bad, copycat of anime. Now maybe wait for the thread to get an answer before continuing this pointless side discussion.


  • Fake News

    @captain First things first, make sure everything is committed, git will do nothing but complain when you have uncommitted changes. And rightly so, because it might very easily lose those changes.

    Create a branch which points to the most recent commit with git branch <yournewname>. Branches are cheap.

    Your workspace still is in detached head mode now because the HEAD reference points directly to the latest commit. Use git checkout <yournewname> to fix that, HEAD will point to your new branch and you should be in a safe state for now.


  • Fake News

    With that said, if you really want to go through with obliterating history then I would seriously recommend backing up the entire local git repo (including .git folder) if this is your first time.

    Of course, if you do the changes in those "outlawed" commits over again by hand then things might not be so dramatic.

    Right now you should have at least two banches, so if you use a command like gitk --all & it should show them both, and you can more easily see what changed.


  • Fake News

    Pick how you go from here: either keep making changes by hand or use git cherry-pick <old commit id> if you want to take whole commits and reapply them in your new branch.

    Choose what you're going to do to the 'parallel' history. Have you pushed your branch somewhere before where anybody else (you care about) could be working on it?
    If so, you could do what Blakey said, leaving the old commits there but "clobbering" their contents by a merge which takes only the file contents of your new branch. Just make sure to change the merge commit message and in it tell what you are doing.

    If it's nowhere pushed then you can simply rename branches, either rename or delete the old branch (backups!) and rename the new branch to take its place (note that I can't remember if you need git checkout again after that), it's been a while since I renamed branches.


  • Fake News

    If it was pushed before then Blakey's method should always work if do git push --set-upstream <repo alias> <yournewbranchname>:<old branchname on server> (Repo alias is likely origin).

    If you used the other method and don't know / don't care about others working on the server then you might need to add a --force parameter to the command above. Since this will tell the server "I know what I'm doing and won't destroy others' work, pinky-swear promise" the server will skip its usual causality checks and store your new branch state. If the server is configured so it might reject your promise stating that you can't force your way out this. If you can't configure the server then you need to fall back to Blakey's method.

    Note that the old history might linger on the server for a few days if you know the old commit id. If this a security issue (committed keys) you want to contact support.



  • @captain said in Walk me through fixing this git thing:

    Git is telling me that I have a detached head. How do I make all the new commits end up in the right place?

    git checkout -b newbranchname
    

    @captain said in Walk me through fixing this git thing:

    Ideally, I'd like to take a quick peek at the "bad" commits I'm deleting to see if there's anything I can salvage. I know there's some good work in there.

    git rebase -i goodbranchname
    # edit the text file it opens as directed
    git checkout goodbranchname
    git reset --hard newbranchname
    

    Also, git reflog is your safety harness.



  • Thanks everybody, I got it all sorted out by branching from my detached HEAD (to a branch called temporary), going back to master's head, branching that to hanging, doing some reverts to get rid of dumb confusing conflicts, and merging everything back into master.

    I'm glad that reflog thing was around though. It was scary not knowing what to do next.


  • Discourse touched me in a no-no place

    @captain said in Walk me through fixing this git thing:

    I'm glad that reflog thing was around though. It was scary not knowing what to do next.

    Sometimes, one gets in a state where things are a bit tricky. That is when it is useful to understand what's really going on under the hood, and not just the tidy models that sit on top. This applies to all sorts of technical systems, from computers to cars to sewage treatment. (I don't want to understand the latter two, FWIW. Especially not the drains and sewage plants.) Git makes that sort of thing relatively available, and it helps to know that you can recover.

    Of course, it's also a bit easier to get into trouble in the first place with Git. I don't like it very much, and I'm glad my IDE does plenty to tame it.


Log in to reply