Lately I'm paying more attention to the Git commands I run to help script Getting Git. I have so much material at this point, I was told to turn some of it into a blog post.
What I've found from speaking and pairing is that most of us aren't as comfortable with Git as we might like to be. It's sharing insight into the Git command options and workflows that developers really seem to enjoy.
So here are three Git commands I use every day. Yes, I'm going to skip git status. No, they aren't Git commands you've never heard.
1: git add -p
So you've been hacking away all day on some changes, then you add all of them with git add . or git add -A.
Oh, the irony.
Leaving aside the heavy handed nature of these commands, you spent all that time crafting changes just to throw them in the Git repository. It's like preparing a nice meal, then shoving it all in your mouth at once.
When I complete my changes, I prefer running git add -p. The -p stands for patch. Running this command allows you to interactively review each of your changes. In doing so you can decide if you want to add the change or not.
While more time consuming than git add ., it's well worth it. More often than not I find some changes I probably don't want to commit -- a comment or debug statement. git add -p provides a final review to ensure my changes are ready to be committed.
2: git commit --amend --no-edit
When working on something, I usually only make one or two commits total. However, given the 10x ratio of reading code versus writing code these commits might happen over a long period of time. In between that time I like to make small, incremental commits -- even if it's just a WIP commit.
For these commits, I like to use git commit --amend --no-edit. Yes, I know I can use git rebase instead. But most of the time work is done sequential. So I don't need to need all that, I can simply append my changes to the previous comment.
This also allows me to keep a clean state, which makes it easier to run other Git commands as well as keep track of my changes over time. It also provides the freedom to spike on some changes that I may not end up using without relying on ⌘-z.
I'll admit, this starts to get into what I consider a commit (which I'll wrote about in my next post).
3: git reset --hard
I know a few of you just freaked out. Some people find git reset scary, especially when run with the --hard option. However I find it complements the other two commands. For example, if there were changes I didn't add with git add -p or changes from a spike I didn't want to commit I can easily discard them with git reset --hard.
Now, that's not to say you should be cavalier with git reset --hard. There are still some scary stories. Simply being mindful will mitigate this fear. In reality, you should never be afraid to run a Git command when armed with git reflog and git fsck.
In the end, I think these 3 Git commands say more to my everyday workflow. Maybe you see how they fit into your own. I explain these and over 20 other Git commands in my upcoming video series Getting Git. Which is now available in early access. And check out my next post on when I make commits.
Oldest comments (20)
Two out of three. :) I have
git patchandgit amendas aliases.Good idea to add aliases for these.
I believe
git reset --hardshould be avoided. Better remove unwanted changes changes withgit checkout --patchand then use--hard's safe brothergit reset --keep.I've been use gitx, which is a pretty version of gitk for ages just for the purpose of reading through commit diffs and writing commit messages, and staging/unstaging files. It supports amend as well, which I use a lot. It's one of those things where having a nice UI to review a lot of diffs quickly is a bonus.
Other than that, my git workflow is entirely command line based. I have two aliases: gitu, and gitc that for git fetch && git pull --rebase and git fetch && git push origin. So with gitx, gitu, and gitc I pretty much have my day to day workflow. I also have a gitl alias tied to a fancy customised git log commandline. Other than that, there's the occasional merge and branch juggling. Maybe an occasional cherry-pick and a reset git --hard in case I have unstaged changes I no longer care about.
While
git add -pis nice, I believe the use case of "hacking all day on some changes" without committing any code should be avoided when possible.Commit early and commit often. This gives me a safety net for when I screw something up. At the end of the day, I can
git rebase -i start-of-dayto clean up the mess. It is a bit less beginner-friendly, but I like it. Then again, I also like splitting commits during a rebase, as it allows me to "test" them individually during the rebase.git-add -pisn't just for hacking all day without committing any code. I use it for two reasons:git diff. It also allows me to exclude things that I don't want to check in, such as random extra bits of logging that I no longer need.git rebase -iwithfixup(orsquash).Note that I also have
git cialiased togit commit --verbose, which shows me the diffs in the editor window at commit time.I totally agree.
git add -pis a wonderful command. But having spent too much time convincing co-workers and friends to commit early, I had to make that comment.I didn't know about
git commit --verbose. That's neat!As far as rebasing workflows go, I like aliasing
git commit --fixuptogit fix, so that I can "fix" any relevant commits. The log ends up looking really weird before the rebase, but since I know where each commit should go, it is not an issue.Sure. I get that. I commit all the time, to the point that my commit comments are generally just things like
safsahghhfdddd, and might only be a line or two.Once I'm starting to be happy with my branch, I go back with
git rebase -i(usingeditandgit reset HEAD~) andgit add -pto split the changes into sensible pieces.Then I reorder the commits and squash/fixup as relevant so that my PR forms a coherent "story".
I frequently find myself pulling smaller refactorings to the start of the branch, so that they can be cherry-picked into master separately from the other changes. This allows other team members to start using those changes immediately, and reduces the number of conflicts.
git bisectis one of the best git commands if you are in trouble :)Git stash is a nice way to handle some aspects of 3!
Similar to your notes on
add .vsadd -p, I prefercheckout -pas an alternative toreset --hard- you can make sure you're not throwing something away that you missed during theaddprocess. It works exactly the same way asadd -p, you can choose to ignore or throw away piece by piece.gitup.co
just try it
In my experience, git reset --hard is nice, but it doesn't get the job fully done because I've added new files or folders, so I often have to use git clean in combination with --hard. As a newbie, I was surprised that you had to use a second step to remove any newly created files after the hard reset and have always been puzzled that it's not a one command kind of thing.
In regards to
git add -p, I personally just usegit diff --staged.That's another good one. I recommend tacking on the
-woption to avoid noisy whitespace changes.The main point is to review your changes before blindly adding them. In the end, whatever command helps you do this is an implementation detail.