This document serves the purpose of listing some GIT commands that I find hard to remember, hard to find information about, hard to use or any combination thereof.
The best way to use this is to CTR+F you way through it.
- GIT Concepts
- Discard changes for a given file
- GIT ADD and REMOVE
- GIT RESET Explained
- GIT IGNORE file
- History
- Alias
- Save password
- GIT GLOBAL file
- Make a local branch track a specific remote branch
- Merge
- Blame
- Rename commit message | Re-write last commit
- Make "branch" point to commit | Move branch
- Update Windows Domain password
- Stash only some files
- Search Stuff
- Show staged or unstaged differences
- Diff'ing
- Squash Commits
- Bisect
- Stop Tracking a file
- Clean or purge files on the repository
Table of contents generated with markdown-toc
HEAD:
How does Git know what branch you’re currently on? It keeps a special pointer called HEAD.
Means "what commit is my repository currently at?" Most of the time HEAD points to the latest commit in your branch, but that doesn't have to be the case.
In the event that the commit HEAD refers to, is not the tip of any branch this is called a "detached head".
Index:
Where you place files you want committed to the git repository.
Put files with "git add" and remove with "git reset".
Many names to the same thing:
- Index
- CacheDirectory
- Current directory cache
- Staging area
- Staged files
All these names refer to the Index.
git checkout -- filename
Undo git add (yes its reset)
git reset -- <file>
Or, "git add" for "file deletions" is not "git add" but "git rm":
git rm --cached -- <file>
git rm -r --cached -- <directory>
https://git-scm.com/blog/2011/07/11/reset.html
With a file-path:
unstages the file (as explained above, undo's git add)
Without a file-path provided, 3 modes:
--soft just move the branch
--mixed (default) move the branch and the index
--hard move the branch and the index and the working copy
This will destroy the last commit and set all changes back into the working-copy and the index (git add
is "preserved").
So that you can resume work (edit, commit, add, undo add, break the comit in several comits, etc).
git reset --soft HEAD^
This will be the same as above, but the index is not preserved so all changes will show as "unstaged". This is also the default behaviour, so not seeting the reset mode is the same as setting mixed.
git reset HEAD^
git reset --mixed HEAD^
This will completly delete the previous commit, changes are lost forever. Done, Hard and simple.
git reset --hard HEAD^
http://git-scm.com/docs/git-check-ignore
Show files being ignored
git status --ignored
Search for the .gitignore
line that matches a give file.
git check-ignore --verbose <path>
If the specified line by this command points to an empty line on .gitignore
, it means that the path provided is NOT being ignored.
Like a boss:
git log --pretty=format:"%h - %an, %ar : %s" --graph --abbrev-commit -45
git log --graph --pretty=format:'%C(yellow)%h%Creset - %C(bold blue)%an%Creset, %Cgreen%ar%Creset : %s' --abbrev-commit
git log -p -2
-p show the difference for each commit
-N show only N commits
Abbreviated statistics for each commit:
$ git log --stat -1
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <[email protected]>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
Rakefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
History for a given file or directory
git log -- C
git log -- A B # where A B or C are the PATHs to a file or directory
Add an Alias
git config --global alias.st "status"
List configured alias
git config --get-regexp alias
Save alias on dropbox ('>' is replace '>>' is append to file, I always confuse teh two)
git config --get-regexp alias > ~/Dropbox/Software/notepad\ files/git_alias.txt
Execute this cmd for git in windows. It ask the password next time and then its saved. Magic.
git config --global credential.helper wincred
Export git configuration:
git config --list
Edit manually the global config file (defaults to vim)
git config --global --edit
Basic Git global configuration
git config --global user.name "Firstname Lastname"
git config --global user.email "your_email"
git config --global color.ui true
git push -u origin master
Merge OTHER into current branch
--no-fast-forward
so that the "history line is kept separate"
git merge --no-ff <other>
Merge dry run OTHER into current branch(if not ok, we can abort and nothing happened)
git merge --no-commit --no-ff <other>
Cancel the ongoing merge (merge pauses on conflicts)
git merge --abort
Preview a merge: Will list all the commits that will be brought to the current branch
-
http://stackoverflow.com/questions/5817579/how-can-i-preview-a-merge-in-git
git log ..otherbranch
Yes, fecth does merge (ff only). With this line we can update/pull changes into a branch without checking it out first. Usefull while working on something on branch A (not ready to commit), but you want to update branch B (master, for example).
# From any branch do:
git fetch origin master:master
When you just want what is upstream (before you're in a conflict state):
git pull -X theirs
With merge
or rebase
the flag is --strategy
or -s
.
The meaning of ours
and theirs
changes within a rebase.
git rebase -s theirs master # --strategy or -s | theirs/ours
# 'theirs' is taking the current branch's changes, not master changes
git merge -s theirs master # --strategy or -s | theirs/ours
# 'theirs' is taking the master's changes, not the current_branch changes
Show the last person to make changes for a given file, on lines A to B (stops on the first commit)
git blame -L A,B -- path/to/file
Same as above, but keeps scrolling back on history
git log -L A,B:<file>
Search All commits where file X was changed (also on the 'Search' Section)
git log --follow -- path/to/X
This will open the editor pre-populated with your previous commit message, so you can change it. (-c is: replace with/pre-populate)
Be carefull if all you want is to rename the commit message. Existing changes will be added to the existing commit.
Always have a clean state before renaming commit messages.
git commit --amend -c HEAD
WARNNING: dont rename commits already pushed or all others who have them checked-out will need to execute:
git pull --force
For older commits than the last one see this:
- https://help.github.com/articles/changing-a-commit-message/
- http://stackoverflow.com/questions/179123/edit-an-incorrect-commit-message-in-git
http://stackoverflow.com/questions/7310177/how-do-i-make-a-branch-point-at-a-specific-commit
git branch -f <branch> <desired-commit> (cannot be on <branch>)
git reset --hard <desired-commit> (must be on <branch>)
WARNING: may loose commits if there are commits without a branch (due to blobs clean up).
After updating the windows domain password git DOES NOT ask for the new password. To solve this:
git config --global credential.helper erase
git config --global credential.helper store
git pull
Now it asked for the new password.
git stash -p
This way you can select which hunks should be added to stash, whole files can be selected as well. You'll be prompted with a few actions for each hunk:
y - stash this hunk
n - do not stash this hunk
q - quit; do not stash this hunk or any of the remaining ones
**a - stash this hunk and all later hunks in the file**
**d - do not stash this hunk or any of the later hunks in the file**
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
**? - print help**
Alternatively we can first move the changes (or hunks) we do not want to stash to the index (git add) and then do
git stash --keep-index
This will only stash what is on the working copy but not on the index.
Replace whatever
with the string to seach for. --source --all
uses all branches.
This will search all the code base for changes where the string whatever
was either added or removed.
git log -Swhatever --source --all
Option 2:
git rev-list --all | xargs git grep -F "whatever"
git log --all --grep='whatever'
It can be useful to define the following git alias for searching:
git config --global alias.find "log --graph --pretty=format:'%Cred%h %Cgreen%s' --grep"
Find all .cs
files and NOT .css
on the current working copy that have un-commited changes:
git status | grep .cs | grep -v .css
Search all commits where file X was changed (This is also on the 'Blame' Section):
git log --follow -- path/to/X
Show unstaged differences:
git diff -- *path to file*
Show staged differences:
git diff --cached -- *path to file*
The difference between staged and unstaged is the following:
- modified a file: change is unstaged
- modified a file: executed:
git add -- file
change is staged
git diff <sha1> <sha2> -- *path to file* # diff <sha1> to <sha2>
If you omit one of the commit-hash the diff is from 'working-copy-changes' to the other commit. Example:
git diff <sha1> -- *path to file* # diff current-changes to sha1
More info at:
# use bc3 even for bc4
git config --global diff.tool bc3
Alternatively, paste this on git config:
[diff]
tool = bc3
[difftool "sourcetree"]
cmd = /usr/local/bin/bcomp -ro $LOCAL $REMOTE
path =
[mergetool "sourcetree"]
cmd = /usr/local/bin/bcomp $LOCAL $REMOTE $BASE $MERGED
trustExitCode = true
Use with:
git difftool --dir-diff
Sometimes, source tree does not pick/see beyond compare as installed. We can manually set this on SourceTree configuration and it will work:
MacOS:
- http://www.scootersoftware.com/support.php?zz=kb_vcs_osx
- From BC4 menu, run "install cmd line tools"
- sourcetree settings / diff / mode custom
- Diff:
/usr/local/bin/bcomp
-ro $LOCAL $REMOTE
- Merge:
/usr/local/bin/bcomp
$LOCAL $REMOTE $BASE $MERGED
-
Never squash or rebase pushed changes
-
Always have a clean state before squash or rebase
-
Checkout the most recent commit of the branch we are going to squash
-
type
git rebase -i HEAD~3
where 3 is the number of commits you want squash -
Git will open vi with something like:
pick f392171 oldest commit pick ba9dd9a the one before pick df71a27 most recent commit
-
edit to this:
pick f392171 oldest commit s ba9dd9a the one before s df71a27 most recent commit
-
save the file and quit:
:wq
-
Git will squash all the commits with
s
intof392171
creating a new commit (so a new hash)
- find a working commit hash (can be a tag or branch name) --
<h1>
- (optional) find a non-working commit hash (can be a tag or branch name) --
<h2>
git bisect start
git bisect bad <h2>
-- no providing h2 will assume HEADgit bisect good <h1>
-- after this git will checkout a commit for you to test- Re-build. Test the issue. Does it work?
- Yes:
git bisect good
- No:
git bisect bad
- repeat until git tells you the commit that introduced the problem
- Yes:
git bisect reset
to put everything back on the original state
Use case:
We want a file to be commited, but each user edits the file with local paths, users etc. Those edits we don't want to commit, but are anoying if they keep showing up on the diff.
So, we tell git to stop tracking the file forever:
git update-index --assume-unchanged path/to/file.txt
If we ever want to commit on that file again:
git update-index --no-assume-unchanged path/to/file.txt
Git can find and delete all ignored files, and files you have locally but are not part of the traked ones.
git clean -xdfn
# -n dry run, just print what would be removed. Take n out actually remove those files
# -x include ignored files on the list
# -d include directories on the list
# -f force when you have weird errors but are sure about the files to remove
Sometimes, the list is to large and we can filter like:
git clean -xdfn -e "*/foo/*" # exclude all entries from the list with "foo" on the path
git clean -xdfn "*/bar/*" "*/foo/*" # include only entries from the list with "foo" or "bar" on the path