Hacker News new | ask | show | jobs
by codetrotter 2497 days ago
I think people trip on these potential foot guns in part because a lot of git commands are long and annoying to type, so you end up working more based on your mental model of the state of the working copy and less based on the actual state of it.

I am not so fond of analogies but I would like to offer up an analogy here anyway. I think for a lot of people, the way that they are using git is akin to utilizing a sharp knife with your hands while your hands are obstructed from your view. You have a certain amount of feeling for what is going on but you are bound to cut yourself now and then if your view of what you are doing is obstructed. In this analogy, your reliance on your mental model of the state of the working copy is obstructing your view of the reality of the state that it is in.

Several years ago I defined a few two-letter shell aliases for the git commands that I use the most.

Maintaining my .bashrc across different systems became a drag though, so I simplified my setup even more.

I wrote two-letter “shell scripts” that just wrap the commands, and just put those in my ~/bin/. This makes it very fast and simple to get up and running on a new laptop, desktop or server.

https://github.com/ctsrc/shell-command-aliases

Said two-letter shell scripts can be found in that repo. There’s a README too, which tells you what each of them do.

My git workflow is simple, efficient and ensures that my view of what I am doing is not obstructed.

I can proudly say that the last time I did something unintended with git that resulted in lost work was long ago that I can’t even remember when. And it all boils down to these two-letter aliases.

When there is friction, identify the friction and remove it. That is what I have done here. Hopefully it might be of use to others too.

Here are some consecutive entries from my bash history that are representative of how I use my aliases while working on something.

    mv ~/tmp/index.htm dimensions.htm
    st
    ls
    dp
    git checkout -- src/
    st
    mv dimensions.htm src/
    st
    mv src/dimensions.htm src/draft.htm
    di
    st
    aa
    cm "Draft."
    le
    le
    vim src/draft.htm 
    st
    vim src/draft.htm 
    aa
    di
    cm "Mirrored, dark/light."
    vim src/draft.htm 
    aa
    di
    vim src/draft.htm 
    aa
    di
    cm "Remove unneccessary declaration."
    vim src/draft.htm 
    aa
    di
    cm "Organize and restructure classes in draft."
    vim src/draft.htm 
    aa
    di
    cm "Increase height of placeholder."
    pu
    le
    st
    st
    dp
    vim src/draft.htm 
I keep a few terminal windows open when I work on a project, and often use one or two of them for git operations, and smaller edits to some files, while also having my IDE open, web browser, etc.

Notably, these two-letter commands make it very fast to remind myself of what the current state of the repository is whenever I've looked something up on the Internet for example, or after I have run tests in another terminal or made multiple different edits in different files in the IDE window, etc.

And I always check the diff before I commit. It's amazing how often you think you are about to commit just one change but when you look at the diff you realize that there are some other smaller changes that you made as well. By always reviewing your diff before you commit, you ensure that you don't commit something that would be better committed separately, and that your commit messages accurately describe the actual changes that you are committing.

2 comments

I do something similar, though I use git's built-in aliasing so that I keep everything namespaced under "git". Mine are, for example, "git st" (status), "git ci" (commit), "git co" (checkout), "git dfc" (diff --cached), etc.

That said, my best advice for folks new to git, or folks who find themselves doing destructive actions often, is to embrace WIP commits. I "checkpoint" work somewhat frequently with "git add -A; git ci -m wip". They can be cleaned up later with soft resets, rebases, or similar. Once a commit is created, it's in the reflog, and it's quite rare to lose that set of work, even if a rebase or reset goes "wrong".

I use prezto's 2-3 letter aliases. But that doesn't help when I run `git reset --hard` (or gwR) and erase changes I don't know exist.

I wish I could move HEAD to a different commit (git reset), and apply (new HEAD - old HEAD) to my working directory (--hard), but abort if working directory != old HEAD.

In fact, this sounds like `git reset --keep`, but unfortunately prezto doesn't have an alias for that.

I don't like prezto's git-reset aliases. gwr is "move HEAD", gir is "move HEAD and reset index", and gwR is "move head, reset index, and reset working directory". I wish gwr was renamed to ghr, and maybe gar (git apply reset) for --keep.