Walid-Shouman
6/23/2016 - 3:38 PM

command of the day series

command of the day series

Selective Patch Using Interactive Mode From the Current Directory

  1. Ensure having a clean index (nothing is staged).
  2. Stage the files of interest (assuming they are the files in src/).
git add src/
  1. Stash interactively what we want for the patch
git stash save -p "stash to be saved"
  1. Save the stash into a file
git stash show -p stash@{0} > current_work.patch
  1. Apply the stash later
git apply current_work.patch

Notes

  • This way is considered a workaround for the issue of git stash show -p stash@{0} doesn't capture the untracked files, as staging files first ensures not having untracked files.
  • There might be an easier practice.
  • We may enter the interactive mode while adding files to index (didn't prefer that as we may already have staged files that we don't want to unstage while getting in this process. Even though it's discouraged to have an unclean index.)
  • I find it useful to store the commit hash within the patch name, or somewhere beside.

activate gitignore

the three steps needed after a new .gitignore file with many files to be untracked

git rm -r --cached .
git add .
git commit -m ".gitignore is working from now on"

Note: Don't forget updating all the branches :sunglasses:
Note: This way shouldn't be used with secrets and files/lines that should be deleted totally from history
Ref.: Stack Overflow answer

Saving current directory changes

Motivation

Having code of logging at a certain commit which you want to save for later.
Having code snippets for an incomplete small fix/cleanup that shouldn't belong to a separate branch, yet it's not a current priority.
Having to do a certain change and try those changes and get back to the development you've been into.
Having to checkout and test the code at a certain point of time while working to compare the code output.

Terminology

HEAD -> resembles the last committed changes Index/cache -> resembles the staged changes (marked green when we use git status) No index -> resembles uncached changes (may include tracked, untracked or removed files)

Examples

List the stashes we have

git stash list

Save a new stash

git stash save "stash_name"

In case we're in hurry we may omit the save and message name

git stash

Restore (Pop) the previous stash into the current directory
Note: we may figure the stash index using git stash list.
Note: stash index changes everytime we pop/save a new stash.

git stash pop stash@{0}

In case we're in a hurry for restoring the previous stash

git stash pop

Note: git stash pop removes the stash from list, git stash apply doesn't.

To show the previous stash content*
Note: without the -p options we're left with the stash stats only

git stash show -p stash@{0}

*untracked files won't be showed in the previous command, as they are stored in the third parent of the stash
This question tackles this point This is the commit that introduced the -u(--include-untracked) option

Customizatons

-p|--patch -> interactive mode --no-keep-index -> stash (staged + unstaged) files
--keep-index -> stash unstaged files (default with --patch option)
-u|--inlcude-untracked -> include untracked files (those are unstaged files)
-a|--all -> include ignored files
Note: we can't combine (--patch and --all ) or (--patch and --include-untracked)
In order to use the interactive mode with untracked/ignored files, stage all the files of interest for the stash using git add and go interactive with those files
My Best Command

git stash save -p --no-keep-index "stash message"

If we don't want to stage and have no problem with getting whole files at once (non-interactive mode) we may use

git stash save --no-keep-index --include-untracked "stash message"

If we don't want to touch the staged

git stash save --keep-index --include-untracked "stash message"

Using --all will result in stashing stuff we don't really care about, typically we don't wanna use it.

Extra Readings

git stash documentation

Branch listing

examples

list branches (local only), note: --list could be omitted

git branch --list

list branches (remote only)

git branch -r

list branches (local and remote)

git branch -a

list branches, order based on committerdate (remote and local)

git for-each-ref --sort=-committerdate

or be specific to local branches only

git for-each-ref --sort=-committerdate refs/heads/

all branches: branch name, last commit message, author and relative date

git for-each-ref --sort=committerdate refs/remotes/ --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))'

extra Readings

ordering branches by recent commit

cherry picking ... topic is based on the study of this article

exchanging commits

creating patches for others

git format-patch HEAD~~

the previous is the same as

git format-patch -2 HEAD

making patches for a revision range

git format-patch some_hash1..some_hash2 --stdout > commit-range-patches.patch

to apply those patches on top of the current work (1 patch at a time) note: git apply doesn't commit, leaves the changes unstaged and uncommitted

using git apply 0001-rest-of-file-name.patch

to apply those patches on top of the current work (many patches at a time)
note: git am commits the changes in patches

git am *.patch

to have multiple patches in one file we do the following (that's what i prefer)

git format-patch -2 HEAD --stdout > 0001-last-2-commits-from-head.patch

and apply it as before using am

git am 0001-last-2-commits-from-head.patch

important note: keep a copy before testing the previous code, wip/local changes may be lost while testing

extra readings

first scenario (with apply example)
multiple files in a patch scenario
the docs for git format-patch
the docs for git apply
the docs for git revision range

logging changes in previous commits

examples

name of the changed files

git log --name-only

name of the changed files & their status (added/modified/deleted ...)

git log --name-status

name of the changed files & insertion/deletion statistics

git log --stat

name of the changed files & file hash & their status & access right change

git whatchanged

extra Readings

the docs for git log
docs for git whatchanged (this one's use is discouraged)

git filter-branch

makes big changes!

ref: https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#The-Nuclear-Option:-filter-branch
http://stackoverflow.com/a/14544544

examples

remove a certain file from all the commits

git filter-branch --tree-filter 'rm -rf some_bad_file' HEAD

to undo the previous command use

git reset --hard refs/original/refs/heads/master

rename old@email to a new@email.com in all the previous commits

git filter-branch --commit-filter '
        if [ "$GIT_AUTHOR_EMAIL" = "old@email" ];
        then
                GIT_AUTHOR_NAME="New Name";
                GIT_AUTHOR_EMAIL="new@email.com";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi' HEAD
git show revision:path/to/file  

shows the file path/to/file at a certain version.
ref: http://stackoverflow.com/a/338470

examples

check the file before the changes that are not commited yet

git show HEAD:app/models/event.rb

check the file before the last commit

git show HEAD~:app/models/event.rb

check the file at any commit

git show some_version_hash:app/models/event.rb