12 February 2018

Git Cheat Sheet

After moving from Subversion to Git, I was rather confused. Working with Subversion was mostly comprised of Update and then Commit. If there was branching involved, things could get messy quickly, but if everyone was working on trunk Subversion was mostly invisible.

Now Git… Git has many commands. Therefore, this list.

A word of warning: these snippets work(ed) for me, but you should try to understand what they do before applying. Some commands have a dry-run mode - use it. If you are not sure about the changes - do not push. That makes it much harder to correct.

Basics

To clone an already existing repository:

git clone <repository>

This creates a subfolder named after the repository. If you want to have two clones, or you want your folder name to be different, just add a name afterwards. Like this:

git clone <repository> <directory>

To get some details about current state, issue

git status

command. This displays info about changed files, deleted files and newly added files which are in Git language called untracked.

Small workflow example

Git is all about branching. To create a new branch from the currently active branch:

git branch <new_branch_name>

Checkout new branch

git checkout <new_branch_name>

Do some work and then

git add .

to include all changes so far, for committing.

After

git commit -m "commit message"

all changes will be committed to current branch of local repository.

To share your work, issue

git push

Since the branch is new, command will fail. So only when the new locally created branch is pushed for the first time we need to

git push --set-upstream origin <new_branch_name>

Now, to get the changes from remote repository, do a

git pull

Exploration

Display all branches

git branch -l

Display all branches, including remote ones

git branch -l -a

Find commits with log message that matches the specified pattern (regular expression):

git log --grep=<pattern>

Find a commit in which a string was added or erased from some file:

git log -S<a_string> --oneline

Show differences between two commits. In my opinion, not very useful, but included for sake of completeness:

git diff

Find all commits by someone:

git log --committer=<someone>

Show all remotes:

git remote -v

Show all branches on the remote:

git remote show <remote_name>

Useful since not all remote branches are present locally.

Branch operations

Delete a local branch:

git branch -d <branch_name>

Force delete a local branch:

git branch -D <branch_name>

Delete a branch from the remote:

git push <remote_name> :<branch_name>

Here remote_name is usually origin.

Create a branch from any specific commit:

git branch <new_branch> <commit>

Rename a branch:

git branch --move [<old_branch>] <new_branch>

Merging

Merge another branch into current one:

git merge <another_branch> 

--no-commit can be added to allow for additional changes, or inspection of merge.

To do a squash merge:

git merge --squash <another_branch>

This applies changes from another_branch into current one as one commit, and does not record merge info.

Often, for purposes of clearer history, it is useful to add --no-ff option, so that a merge commit will be created even if it will be empty:

git merge --no-ff <another_branch>

When things go wrong

If, changes have been made to a wrong branch, but nothing was committed, the following sequence of commands transports changes to a different branch:

git stash -u
(optionally) git branch <some_other_branch>
git checkout <some_other_branch>
git stash pop

Here, -u ensures that untracked files are also added to stash.

Undo the changes to a file

git checkout -- <path/to/a_file.ext>

Undo all the changes to tracked files

git checkout .

This changes the tracked files back to their last committed state. Untracked, i.e. new files, should be deleted manually.

Alternatively,

git reset --hard

can be issued to reset the branch to the last committed state.

If a commit has just been created, but was not pushed, it can be undone with

git reset --hard HEAD^

If it was pushed,

git revert <bad_commit>

creates a new commit which reverts the effects of the bad one. To inspect (and modify) changes before committing add --no-commit

To undo a merge which has not been pushed:

git reset --hard <remote>/<branch_name>

This will get the local branch in sync with remote one.

For undoing a merge that has been pushed there is no simple recipe.

Ignored files

Git keeps list of the patterns for ignored files in .gitignore file. To determine why a file is being ignored by Git, do:

git check-ignore -v <filename>

Adding entries to .gitignore does not affect already tracked files. For Git to stop tracking a file it needs to be removed from the index.

git rm --cached <file>

To remove a whole directory from index, along with its subdirectories, navigate to it and issue:

git rm --cached *

Other

To set a config variable:

git config <variable> <value>

For example, to set the Notepad as an editor for commit messages:

git config core.editor notepad

Create a patch file:

git diff <from-commit> <to-commit> > output-file

Squash last n commits into one.

git reset --soft HEAD~<n>

Do this only when commits were not pushed.

Apply arbitrary commits from other branches to current branch:

git cherry-pick <commit1> [<commit2>...]

--no-commit can be added to inspect proposed changes.

Delete untracked files

git clean -f

Add -n for dry run, -d for directories, -x to also delete ignored files

Still more useful information

If you are on Windows, don’t forget to check out posh-git. It adapts PowerShell command prompt with status information of the repository and provides autocompletion support.

Useful links: