Git from the Bottom Up – Reset, Stash, and Reflog

2:04:43
 
Share
 

Manage episode 343520941 series 27319
By Allen Underwood, Michael Outlaw, and Joseph Zack. Discovered by Player FM and our community — copyright is owned by the publisher, not Player FM, and audio is streamed directly from their servers. Hit the Subscribe button to track updates in Player FM, or paste the feed URL into other podcast apps.

We wrap up Git from the Bottom Up by John Wiegley while Joe has a convenient excuse, Allen gets thrown under the bus, and Michael somehow made it worse.

The full show notes for this episode are available at https://www.codingblocks.net/episode195.

Sponsors

  • Retool – Stop wrestling with UI libraries, hacking together data sources, and figuring out access controls, and instead start shipping apps that move your business forward.
News
  • Thanks for the reviews on iTunes jessetsilva, Marco Fernandooo, and sysadmike702!
In Conclusion, … Git Reset
  • Git’s reset is likely one of the commands that people shy away from using because it can mess with your working tree as well as what commit HEAD references.
  • reset is a reference editor, an index editor and a working tree editor.
git reset Modifies HEAD? Modifies the index? Modifies the working tree? --mixed YES YES. Removes all staged changes from the index, effectively unstaging them back to the working tree. YES. All changes from the reset commit(s) are put in the working tree. Any previous changes are merged with the reset commit(s)’s changes in the working tree. --soft YES YES. All changes from the reset commit(s) are put in the index. Any previously staged changes are merged with the reset commit(s)’s changes in the index. NO. Any changes in the working tree are left untouched. --hard YES YES. Clears the index of any staged changes. YES. Clears the working tree of any unstaged changes. What do the git reset mode flags change? Mixed reset
  • --mixed is the default mode.
  • If you do a reset --mixed of more than one commit, all of those changes will be put back in the working tree together essentially setting you up for a squash of those commits.
Soft Reset
  • These two commands are equivalent, both effectively ignoring the last commit:
    • git reset --soft HEAD^
    • git update-ref HEAD HEAD^
  • If you did a git status after either of the previous commands, you’d see more changes because your working tree is now being compared to a different commit, assuming you previously had changes in your working tree.
    • This effectively allows you to create a new commit in place of the old one.
      • Instead of doing this, you can always do git commit --amend.
  • Similar to the use of --mixed for multiple commits, if you do a reset --soft of more than one commit, all of those changes will be put back in the index together essentially setting you up for a squash of those commits.
Hard Reset
  • This can be one of the most consequential commands.
  • Performing git reset --hard HEAD will get rid of any changes in your index and working tree to all tracked files, such that all of your files will match the contents of HEAD.
  • If you do a reset --hard to an earlier commit, such as git reset --hard HEAD~3, Git is removing changes from your working tree to match the state of the files from the earlier commit, and it’s changing HEAD to reference that earlier commit. Similar to the previous point, all uncommitted changes to tracked files are undone.
    • Again, this is a destructive/dangerous way to do something like this and there is another way that is safer:
      • Instead, perform a git stash followed by git checkout -b new-branch HEAD~3.
        • This will save, i.e. stash, your index and working tree changes, and then check out a new branch that references HEAD‘s great grandparent.
        • git stash saves your work in a stash that you can then apply to any branch you wish in the future; it is not branch specific.
        • Checking out a new branch to the older state allows you to maintain your previous branch and still make the changes you wanted on your new branch.
  • If you decide that you like what is in your new branch better than your old branch, you can run these commands:
    • git branch -D oldbranch
    • git branch -m newbranch oldbranch
  • After learning all of this, the author’s recommendation is to always do the stashing/branch creation as it’s safer and there’s basically no real overhead to it.
  • If you do accidentally blow away changes, the author mentions that you can do a restore from the reflog such as git reset --hard HEAD@{1}.
  • The author also recommends ALWAYS doing a git stash before doing a git reset --hard
    • This allows you to do a git stash apply and recover anything you lost, i.e. nice backup plan.

As mentioned previously, if you have other consumers of your branch/commits, you should be careful when making changes that modify history like this as it can force unexpected merges to happen to your consumers.

Stashing and the Reflog
  • There are two new ways that blobs can make their way into the repository.
    • The first is the reflog, a metadata repository that records everything you do in your repository.
      • So any time you make a commit in your repository, a commit is also being made to the reflog.
      • You can view the reflog with git reflog.
    • The glorious thing about the reflog is even if you did something like a git reset and blew away your changes, any changes previously committed would still exist in the reflog for at least 30 days, before being garbage collected (assuming you don’t manually run garbage collection).
      • This allows you to recover a commit that you deleted in your repository.
  • The other place that a blob can exist is in your working tree, albeit not directly noticeable.
    • If you modified foo.java but you didn’t add it to the index, you can still see what the hash would be by running git hash-object foo.java.
    • In this regard, the change exists on your filesystem instead of Git’s repository.
  • The author recommends stashing any changes at the end of the day even if you’re not ready to add anything to your index or commit it.
    • By doing so, Git will store all of your working tree changes and current index as the necessary trees and blobs in your git repository along with a couple of commits for storing the state of the working tree and index.
    • The next day, you come back in, run a git stash apply and all of your changes are back in your working tree.
      • So why do that? You’re just back in the same state you were the night before, yeah? Well, except now those commits that happened due to the stash are something you can go back to in your reflog, in case of an emergency!
  • Another special thing, because stashes are stored as commits, you can interact with them just like any other branch, at any time!
    • git checkout -b temp stash@{32}
      • In the above command, you can checkout a stash you did 32 days ago, assuming you were doing a single stash per day!
  • If you want to cleanup your stash history, DO NOT USE git stash clear as it kills all your stash history.
    • Instead, use git reflog expire --expire=30.days refs/stash to let your stashes expire.
  • One last tip the author mentioned is you could even roll your own snapshot type command by simply doing a git stash && git stash apply.
Resources we Like Tip of the Week
  • A couple episodes back (episode 192), Allen mentioned Obsidian, a note taking app that operates on markdown files so you can use it offline if you want or you can keep the files in something like DropBox or pay a monthly fee for syncing. Good stuff, and if you ever want to leave the service … you have the markdown files! That’s an old tip, but Joe has been using it lately and wanted add a couple supplemental tips now that he’s gotten more experience with it.
    • If Obsidian just manages markdown files, then why bother? Why not just use something like VSCode? Because, Obsidian is also a rich client that is designed to help you manage markdown with features built in for things like search, tags, cross-linking etc.
    • Obsidian supports templates, so you can, for example, create a template for common activities … like if you keep a daily TODO list that has the same items on it every day, you can just {{include}} it to dump a copy of that checklist or whatever in. (help.obsidian.md)
    • Obsidian is designed to support multiple “vaults” up front. This lets you, for example, have one vault that you use for managing your personal life that you choose to sync to all of your devices, and one for work that is isolated in another location and doesn’t sync so you don’t have to worry about exfiltrating my work notes.
    • Community extensions! People have written interesting extensions, like a Calendar View or a Kanban board, but ultimately they serialize down to markdown files so if the extension (for example) doesn’t work on mobile then you can still somewhat function.
    • All of the files that Obsidian manages have to have a .md file extension. Joe wanted to store some .http files in his vault because it’s easy to associate them with his notes, but he also wanted to be able to execute them using the REST Client extension … which assumes a .http extension. The easiest solution Joe found was just to change the file type in the lower right hand corner in VSCode and it works great. This works for other extensions, too, of course! (GitHub)
  • [Wireless] How to improve compatibility of IoT device with ASUS WiFi 6(AX) Router? (ASUS)
  • Google’s new mesh Wi-Fi solution with support for Wi-Fi 6e is out, Google Nest Wifi Pro, and looks promising. (store.google.com)
  • Terran Antipodes sent Allen a tip that we had to share, saying that you can place your lower lip between your teeth to hold back a sneeze. No need to bite down or anything, it just works! All without the worry of an aneurysm.

202 episodes