This final chapter presents some commands and recipes for accomplishing a grab bag of specific tasks. Some were presented earlier and are repeated or referred to here for easy reference, and some are new. Remember that you don’t usually want to edit history for commits you’ve already published with
git push. Examples that refer to a remote repository use the most common case,
rev is any revision name as described in Chapter 8.
Suppose you have an account named
ares on a server
mars.example.com, which you want to use to coordinate your own work on a project
foo (perhaps among repositories at home, work, and on your laptop). First, log into the server and create a “bare” repository (which you will not use directly):
$ ssh firstname.lastname@example.org ares> git init --bare foo Initialized empty Git repository in /u/ares/foo/.git $ logout
If this is for a project with existing content, connect that repository to the new remote as its origin (assuming here a single, local master branch):
$ cd foo $ git remote add origin email@example.com:foo $ git push -u origin master ... To firstname.lastname@example.org:foo * [new branch] master -> master Branch master set up to track remote branch master from foo.
You can just use plain
git push from then on. To clone this repository elsewhere:
$ git clone email@example.com:foo
$ git commit --amend
-a to automatically stage all changes to tracked files (skipping
git add). Add
-C HEAD to reuse the previous commit message without stopping to edit it.
$ git rebase -i HEAD~n
$ git reset HEAD~n
This removes the last n commits of a linear history from the current branch, leaving the corresponding changes in your working files. You can add
--hard to make the working tree reflect the new branch tip, but beware: this will also discard any current uncommitted changes, which you will lose with no recourse. See Discarding Any Number of Commits. This will also work if there is a merge commit in the range, effectively undoing the merge for this branch; see Chapter 8 to understand how to interpret
HEAD~ in this case.
$ git commit --reset-author -C rev
$ git cherry-pick rev
$ git --git-dir ~/other/.git format-patch -1 --stdout rev | git am
$ git diff --name-only --diff-filter=U
$ git status
$ git add -A
git add for every changed, new, and deleted file in your working tree. Add
--force to include normally ignored files; you might do this when adding a new release to a “vendor branch,” which tracks updates to other projects you obtain by means other than Git (e.g., tarballs).
git diff shows unstaged changes; add
--stage to see staged changes instead. Add
--name-status for a more compact listing.
git stash saves and sets your outstanding changes aside, so you can perform other operations that might be blocked by them, such as checking out a different branch. You can restore your changes later with
git stash pop. See git stash.
$ git branch foo origin/foo
$ git ls-tree -r --name-only rev
git show is easier that
git diff , and shows the author, timestamp, commit ID, and message as well. Add
-s to suppress the diff and just see the latter information; use
--stat to summarize the changes. It also works for merge commits, showing conflicts from the merge as with
git log --cc (see Showing Diffs). The default for
rev is HEAD.
Git comes with a completion package for bash and zsh, installed in its
git-core directory as
git-completion.bash. You can use it by including (or “sourcing”) this file in your shell startup file (e.g., in
# define completion for Git gitcomp=/usr/share/git-core/git-completion.bash [ -r $gitcomp ] && source $gitcomp
Pressing Tab in the middle of a Git command will then show possible completions for the given context. For example, if you type
git checkout, space, and then press Tab, the shell will print the branches and tag names you could use here. If you type an initial part of one of these names, pressing Tab again will complete it for you. The exact behavior of completion is very customizable; see your shell manpage for details.
There is also a
git-prompt.sh, which will make your shell prompt reflect the current branch status when your working directory is a Git repository.
$ git remote -v origin http://olympus.example.com/aphrodite (fetch) origin http://olympus.example.com/aphrodite (push)
$ git remote set-url remote URL
$ git remote prune origin
$ git log -g
See Double Oops!.
A root commit always shows the addition of all the files in its tree, which can be a large and uninformative list; you can suppress this with:
$ git config [--global] log.showroot false
$ git log --name-status $ git log --stat
$ git log --format=fuller