My git practices have evolved quite a bit since .
This article would thus be severely due for an update.
Reminder: In my status quo I document the commands from the perspective of how I use them, which necessarily (and by design) involves (over)simplifications.
Please consult the official documentation for full details.
Once again, I'm making quite unsophisticated use of a sophisticated tool.
My workflows are really simple, owing in large part to the fact that I'm mostly a "lone-wolf" open-source programmer: I pretty much never work on third-party projects (j'ai d'autres chats à fouetter!), and I'm typically the only contributor to my projects (which is fine by me!), besides occasional outside feedback (which I could use more of!).
And I rarely use branches other than the default,
master. Juggling the state of 50+ projects is already hard enough without also having multiple branches per project... Besides, even google does everything on the master branch, I hear...
And since I push regularly, usually just after each commit, even if it's incomplete work, and rebasing publicly shared history is a Very Bad Thing, I never rebase either. My days of hiding my work until everything is "perfect" are over...
So, no branches, no contributors, no patches, no rebasing, no complexity, no nothing. Simple. Excruciatingly simple.
git status -s
Show the state of the working tree and staging area relative to the HEAD.
I never ever use
git status, I just find it harder to read.
I haven't yet gotten around to making
git statusbehave like
git status -s. I know there's a simple way to configure that globally...
git diff [path]
git diff --cached [path]
Show the diff between the working tree and the staging area, or between the staging area and the HEAD, respectively.
If a path is given, show the diff only for files matching it.
git add paths…
Add the given files and directories in the working directory to the staging area.
git add .to add all changes to the staging area.
This also adds files which were previously untracked by git.
(As long as they haven't been
I usually instead use the
git committo effectively skip the staging area, but
git addis sometimes useful to prepare specific changes for the next commit, and is also required to add new (as opposed to merely modified) files to the next commit.
I usually use the
-aoption instead of
git adding files individually.
I almost always use the
-moption to specify the commit message on the command line, since it's usually a one-liner in my case. I always use single-quote escapes to make sure all characters are automatically escaped. For example:
git commit -am 'This is my commit message. It'\''s really cool!'
Note the use of
'\''to effectively escape the single quote within the single quote escape.
By the way,
git commit -am "This is my commit message. It's really cool!"wouldn't work as intended (at least with bash) since
!is still interpreted as a special command even within double quotes. And forget
git commit -am "This is my commit message. It's really cool\!"because it would yield a commit message of "This is my commit message. It's really cool\!". Yeah, shell scripting is screwy like that. So now you see why I ALWAYS use single-quote escapes in this case...
I also sometimes use
git commit --amend, but only if I screwed up the commit message, else I just go with a manual
git reset HEAD^, etc.
git push [remote [branch]]
By default, pushes the current branch (HEAD) to the origin.
--tagsoption to also push all local tags.
Sometimes, after pushing to one of my websites, I notice a mistake, and since I haven't yet pushed to github, I, hum, "do a little dance" that I'll document elsewhere at some point, and at the end of it all I do
git push -f live.
git log [paths…]
Show past commits on the current branch. If paths are specified, show only the commits that affected those paths.
git rm files…
git rm -r directories…
Deletes a file or directory (respectively) from the working tree, and "adds its removal" to the staging area.
git checkout branch
Switch to the given branch. It's best to have a clean working tree when doing so.
With the -b option, create the given branch (pointing at the HEAD commit) and immediately switch to it.
git checkout [tree-ish] paths…
Revert the files matched by the paths to the version of them from the tree-ish, which is typically a commit but (perhaps surprisingly) defaults to the staging area (I would have expected from the HEAD).
git reset paths…
Pretty much the opposite of
git add paths.
Initializes a git repository, creating a
I use the
--bareoption for website deployment repositories, with a post-receive hook that automatically checkouts the code on push.
git clone url
Do I really need to explain what this does?
Anyway, I almost never use this since I have a directory of git repos with all my projects already cloned so I can start working on any of them whenever I like... and as I said, I don't really mingle with third-party projects... so very little cloning for me.
git remote add name url
git remoteonly to setup website remotes, like this:
git remote add live ssh://domain/home/public/.git
As I said, I don't use (non-master) branches often, so not very interesting in my case.
git branchshows the branches.
git checkout -b branch-nameto create new branches (and immediately switch to them).
git branch -d branchwhen I'm done with a branch, after merging it.
git merge branch
Rarely using branches and almost never interacting with third-party patches implies that I almost never merge either...
Merges the branch into the current branch.
git reset --hard commit
Set the current branch head (HEAD) to commit, throw away all your changes to the index and working tree and update them to match that commit. Especially if commit is older than the HEAD, as is typically the case, some commits might be no longer referenceable and thus basically lost (reflog aside).
Useful to quickly obliterate failed experiments. Dangerous command, proceed with caution!
I have one custom command alias in my
[alias] unpushed = log HEAD ^origin/master