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:
- Official Git documantation
- Official Git cheat sheet
- Git related articles on Sara Ford’s Blog
- TortoiseGit when you want a more visual look into Git, e.g. for resolving conflicts
- what
git reset
does