Skip to content

Instantly share code, notes, and snippets.

@vetras
Last active May 27, 2021 13:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vetras/de7bda0783c087cfb75e to your computer and use it in GitHub Desktop.
Save vetras/de7bda0783c087cfb75e to your computer and use it in GitHub Desktop.
List of Usefull Git commands

Git Commands

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.

How to use this document

The best way to use this is to CTR+F you way through it.


Table Of Contents

Table of contents generated with markdown-toc


GIT Concepts

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.

Discard changes for a given file

git checkout -- filename

GIT ADD and REMOVE

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>

GIT RESET Explained

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

Examples

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^

GIT IGNORE file

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.

History

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 <schacon@gee-mail.com>
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

Alias

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

Save password

Execute this cmd for git in windows. It ask the password next time and then its saved. Magic.

git config --global credential.helper wincred

GIT GLOBAL file

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

Make a local branch track a specific remote branch

git push -u origin master

Merge

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

Merge without checkout

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

Resolving Merge conflicts "automatically"

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

Blame

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

Rename commit message | Re-write last commit

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:

Make "branch" point to commit | Move branch

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).

Update Windows Domain password

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.

Stash only some files

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.

Search Stuff

Search for a string in code history

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"

Search for a string in commit messages

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"

Search current modifications for all files of a given extension

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

Search all commits where file X was changed (This is also on the 'Blame' Section):

git log --follow -- path/to/X

Show staged or unstaged differences

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

Diff'ing

Terminal

 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:

Git Config

# 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

SourceTree

Sometimes, source tree does not pick/see beyond compare as installed. We can manually set this on SourceTree configuration and it will work:

MacOS:

Squash Commits

  1. Never squash or rebase pushed changes

  2. Always have a clean state before squash or rebase

  3. Checkout the most recent commit of the branch we are going to squash

  4. type git rebase -i HEAD~3 where 3 is the number of commits you want squash

  5. Git will open vi with something like:

       pick f392171 oldest commit
       pick ba9dd9a the one before
       pick df71a27 most recent commit
    
  6. edit to this:

       pick f392171 oldest commit
       s ba9dd9a the one before
       s df71a27 most recent commit
    
  7. save the file and quit: :wq

  8. Git will squash all the commits with s into f392171 creating a new commit (so a new hash)

Bisect

  1. find a working commit hash (can be a tag or branch name) -- <h1>
  2. (optional) find a non-working commit hash (can be a tag or branch name) -- <h2>
  3. git bisect start
  4. git bisect bad <h2> -- no providing h2 will assume HEAD
  5. git bisect good <h1> -- after this git will checkout a commit for you to test
  6. Re-build. Test the issue. Does it work?
    1. Yes: git bisect good
    2. No: git bisect bad
    3. repeat until git tells you the commit that introduced the problem
  7. git bisect reset to put everything back on the original state

Stop Tracking a file

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

Clean or purge files on the repository

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment