Using Git from the command line

When I was a Git beginner I used TortoiseGit. TortoiseGit had all the features I had ever needed at the time. I could check out branches, stage files for commit, commit changes, push the branches, and do merges. I could even do a “fetch’n rebase.” Over time, as I became more and more familiar with Git, I switched over to using the command line.

I use Git from the command line for several reasons:

  • It is much faster than using a GUI. With a GUI I have to find the places where I need to click, click on the right buttons or items, make sure the right checkboxes are checked, click in the textbox so I can type my commit message, switch between keyboard and mouse again, and so on. With the command line I just type my desired command (e.g., git commit -m "Some nice commit message"), hit Enter, and then I’m done.
  • I think in terms of Git commands. I’d rather just type the commands than translate them into a sequence of actions the GUI requires me to take.
  • Git is much more powerful from the command line. All Git features are available in the command line. On the other hand, GUIs omit some less common or advanced features such as reverting a merge commit.
  • Because I type the commands in myself, it is easier to understand what Git is actually doing. In contrast, GUIs are an abstraction layer built on top of the Git commands and often hide (or make less visible) important details that I would see in the command line.
  • Sometimes I work in environments where there is no desktop GUI, and Git must be used from the command line.

Below I will go over some common Git commands. This documentation is of course not comprehensive, but they should cover most of the use cases I’ve run into.

Shortcuts

Configuration

NOTE: For the below git config commands, add the --global flag to read/write configuration settings at the user-specific level (~/.gitconfig), or --system to read/write the settings at the system-wide level ($(prefix)/etc/config). If neither of these flags are used, the settings are read or applied at the project level.

To list all the configuration options in your project:

git config --listCode language: Bash (bash)

To set your name and email in the commits you author:

git config user.name "Your Name"
git config user.email "your.name@example.com"Code language: Bash (bash)

To automatically prune remote-tracking branches that no longer exist in the remote after each fetch/pull:

git config fetch.prune trueCode language: Bash (bash)

To set the behavior of git push (without any other parameters) to push the current branch to a remote branch of the same name:

git config push.default currentCode language: Bash (bash)

To tell Git to not mess with line endings on checkout or push (i.e., checkout as is, commit as is):

git config core.autocrlf falseCode language: Bash (bash)
  • This is important in situations where you’re working in Windows but for technical reasons some files need to have Unix line endings.

Listing branches

To list all your local branches:

git branchCode language: Bash (bash)

To list all remote branches:

git branch -rCode language: Bash (bash)

To list all your local branches matching some pattern:

git branch -l "feature/some-pattern-*"Code language: Bash (bash)

To list all local branches that have been merged into your current branch:

git branch --mergedCode language: Bash (bash)

Listing tags

To list all tags:

git tagCode language: Bash (bash)

To list all tags matching some pattern:

git tag -l "1.2.*"Code language: Bash (bash)

Branch operations

To create a new branch at the HEAD:

git branch new-branchCode language: Bash (bash)
  • If the new branch already exists, add the -f option to force the creation.
  • To create a new branch somewhere else, add a starting point as the fourth parameter.

To rename the current branch:

git branch -m new-branchCode language: Bash (bash)
  • If the new branch already exists, use either -mf or -M in place of -m to force the renaming.

To delete one or more branches:

git branch -d branch-1 branch-2Code language: Bash (bash)
  • If a branch already exists, use either -df or -D in place of -d to force the deletion.

Tag operations

To create a new local tag at the HEAD:

git tag 1.2.3Code language: Bash (bash)
  • To create a new tag somewhere else, add a starting point as the fourth parameter.
  • If the tag already exists, use -f or --force to update the tag locally.
  • Remember, a tag is not yet in the remote until it is pushed.

To delete one or more tags:

git tag -d 1.0.1 1.0.2Code language: Bash (bash)

Checking out branches

To checkout an existing branch:

git checkout some-branchCode language: Bash (bash)
  • You can also specify a tag or SHA-1 in place of the branch name.
  • Add the --detach option to enter a detached state.

To checkout a new branch at the HEAD:

git checkout -b new-branchCode language: Bash (bash)
  • If the new branch already exists, use either -bf or -B to force the checkout and reset that branch to the current HEAD.

To checkout the last branch you were on previously:

git checkout -Code language: Bash (bash)

To enter a detached state:

git checkout --detachCode language: Bash (bash)
  • Add a starting point as the fourth parameter to reset to that point before detaching.

File operations

To stage the changes in one or more files or directories for commit:

git add path/to/file path/pattern/*Code language: Bash (bash)

To unstage the changes in one or more files or directories:

git restore --staged path/to/file path/pattern/*Code language: Bash (bash)

To remove unstaged changes from one or more files or directories, while preserving the staged changes:

git restore path/to/file path/pattern/*Code language: Bash (bash)

To revert (hard reset) one or more files or directories:

git checkout -- path/to/file path/pattern/*Code language: Bash (bash)
  • There must be spaces on both sides of the -- separator.
  • Add a starting point before the -- separator to change the file’s contents to whatever they are at that point.

To remove one or more files:

git rm path/to/file path/pattern/*Code language: Bash (bash)
  • Add the -r option if you need to recursively remove a directory.
  • Add the --cached option to remove the file from the Git index without removing it from your filesystem. (I suggest only doing this if you’re adding said file to .gitignore.)

To remove all untracked files recursively:

git clean -dfCode language: Bash (bash)

Displaying the status

To show the working tree status:

git statusCode language: Bash (bash)

Displaying diffs

To show changes that have not yet been staged:

git diffCode language: Bash (bash)

To show changes that have been staged:

git diff --cachedCode language: Bash (bash)

To show both staged and unstaged changes at once:

git diff HEADCode language: Bash (bash)
  • To show the changes since a different starting point, replace HEAD with that revision.

To show changes from one revision to another:

git diff revision-1 revision-2Code language: Bash (bash)
  • The starting revision comes first, followed by the destination revision.
  • Normally, you should put the earlier revision first. Reversing the order of the revision parameters would reverse the diff.
  • If the revisions are on separate branches that have diverged, the resulting changes would be the reverse diff from the first revision down to the merge-base of the two revisions, plus the forward diff from the merge-base to the second revision.

To show which files have been changed without showing the actual diff:

git diff --statCode language: Bash (bash)
  • The width of the output usually defaults to 80 characters. If you see file names being truncated, you can increase the width, like in this example:
git diff --stat=200Code language: Bash (bash)

To show the contents of the last commit:

git showCode language: Bash (bash)

To show the contents of any other commit:

git show some-commitCode language: Bash (bash)

Committing changes

To commit staged changes only:

git commitCode language: Bash (bash)
  • This will bring up a text editor (usually Vim) where you can edit the commit message. By default, lines beginning with # will not be part of the commit message.

To set the commit message inside the command, bypassing the text editor:

git commit -m "Some nice commit message"Code language: Bash (bash)

To stage all changes before committing:

git commit -aCode language: Bash (bash)
  • NOTE: This will not add new files to the commit. The quickest way to add all changes to the index, including the untracked (but not ignored) files, is to run git add ..

To amend the last commit:

git commit --amendCode language: Bash (bash)

Resetting

To remove all uncommitted changes from the current working tree (hard reset):

git reset --hardCode language: Bash (bash)
  • If you add a starting point, it moves the current branch to that spot in addition to removing all uncommitted changes.
  • I commonly use git reset --hard HEAD~1 to completely undo my last commit.

To unstage (but retain) all uncommitted changes (mixed reset):

git resetCode language: Bash (bash)
  • The --mixed option is enabled by default. You may choose to add it explicitly if you’d like.
  • If you add a starting point, it moves the current branch to that spot, but the working tree is preserved. That is, the difference between the starting point and where the HEAD was is added as unstaged changes.

To move the current branch while retaining both the working tree and index:

git reset --soft some-starting-pointCode language: Bash (bash)
  • This is similar to a mixed reset except that the difference between the starting point and where the HEAD was becomes staged.
  • You can use git reset --soft HEAD~1 if you need to edit your last commit but want to keep the existing changes staged.

Merging

To merge a branch (or branches) into the current branch:

git merge some-branchCode language: Bash (bash)
  • You may also merge tags and SHA-1s.
  • Typically, the best practice is to merge only one branch at a time. If you merge multiple branches at once, this is called an “octopus merge.”
  • By default, merges are fast-forward (-ff) if the branch to merge already contains the HEAD.
  • Use the --no-ff option to create a merge commit even if the branch to merge already contains the HEAD.

To continue merging after all conflicts have been resolved, you have two options:

git commitCode language: Bash (bash)
git merge --continueCode language: Bash (bash)
  • The difference is that git merge --continue simply calls git commit after checking if there is a merge in progress.

To abort a merge (especially when there is a conflict):

git merge --abortCode language: Bash (bash)

Rebasing

To replay commits from your current branch onto another branch, beginning after the point where the branches diverged:

git rebase some-branchCode language: Bash (bash)
  • This will drop the affected merge commits from the rebase TODO list. To include merge commits, add the -r or --rebase-merges option.

To perform an interactive rebase:

git rebase -i some-branchCode language: Bash (bash)

To continue rebasing after all conflicts have been resolved:

git rebase --continueCode language: Bash (bash)

To abort a rebase (especially when there are conflicts):

git rebase --abortCode language: Bash (bash)

Cherry-picking

To cherry-pick one or more commits:

git cherry-pick commit-1 commit-2Code language: Bash (bash)
  • Commits are cherry-picked in the order you supply them.
  • If you supply a branch name, the commit that the branch is pointing to will be cherry-picked.
  • Add the -n or --no-commit option to cherry-pick the changes from those commit without committing them to the current branch.

To cherry-pick commits that are on another branch but not in HEAD:

git cherry-pick ..some-branchCode language: Bash (bash)

To continue cherry-picking after all conflicts are resolved:

git cherry-pick --continueCode language: Bash (bash)

To abort a cherry-pick (especially when there are conflicts):

git cherry-pick --abortCode language: Bash (bash)

Reverting commits

To revert one or more commits:

git revert commit-1 commit-2Code language: Bash (bash)
  • Commits are reverted in the order you supply them.
  • A commit is created for each commit you revert.
  • If you supply multiple commits, Git will stop after each commit and make you run git revert --continue to patch the commits one-by-one until you are done.
  • Add the -n or --no-commit option to undo the changes from those commits without committing them to the current branch. By following this action with git commit, you can put all those reverts into a single commit.
  • The above command will not work for merge commits. To revert the changes that were introduced into the current branch by a merge commit:
git revert -m 1 some-merge-commitCode language: Bash (bash)
  • There is some documentation written by Linus Torvalds giving details on how to deal with faulty merges. It is common to continue development on the offending branch after the merge commit has been reverted. To do this, first fast-forward (a.k.a. reset) the offending branch to the commit that reverted the merge, then revert the revert.

To continue reverting (especially after all conflicts have been resolved):

git revert --continueCode language: Bash (bash)

To abort a revert (especially when there are conflicts):

git revert --abortCode language: Bash (bash)

Reading from the repository

To update the remote-tracking branches without merging:

git fetchCode language: Bash (bash)
  • If you don’t have fetch.prune enabled, you can add the -p option to prune remote-tracking branches that no longer exist in the remote. The same applies when you run git pull.

To do both a fetch and an immediate merge of the upstream remote-tracking branch into your current branch:

git pullCode language: Bash (bash)
  • Add the -r or --rebase option to do a rebase instead of a merge. If the local and upstream branches have diverged, the best practice is to do a rebase to replay the commits on top of the upstream.
  • If there is no upstream assigned to the current branch, this will do a fetch only and then complain that there is no upstream.

Writing to the repository

To perform the default push behavior:

git pushCode language: Bash (bash)
  • Use the above command to push the current branch if push.default is set to current.
  • Otherwise, you can tell Git explicitly which branches or tags to push.
git push origin branch-1 branch-2Code language: Bash (bash)
  • Add the -u or --set-upstream option to have the local branch track the remote branch as the upstream.
  • Add the -f or --force option to force a push even if the local branch and remote branch have diverged. This option is often necessary if you need to rebase a branch after you had already pushed it. Please use caution, though, as work can be lost if you are not careful.

To remove one or more remote branches or tags:

git push origin -d branch-1 branch-2 Code language: Bash (bash)

Displaying commit logs

To show the commit logs on the current branch:

git logCode language: Bash (bash)

To show the commit logs with a text-based graphical representation of the history:

git log --graphCode language: Bash (bash)

To show the commit logs on a different branch:

git log some-branchCode language: Bash (bash)

To show the commit logs for one or more files or directories:

git log -- path/to/file path/pattern/*Code language: Bash (bash)
  • When filtering by directory, commits that changed any file inside that directory or recursive subdirectories are shown.
  • To exclude merge commits from the logs, add the --no-merges option before the -- separator.

Annotations

To show which revision and author last modified each line of a file:

git blame path/to/fileCode language: Bash (bash)
  • Add a revision as the following parameter to show the file and annotations as it was at that revision.

Leave a Reply

Your email address will not be published. Required fields are marked *