Skip to main content

Miscellaneous Short Notes

Unix/Linux/BSD

'diff' Directories and Their Contents

To diff different directories and their contents, showing a) files present in one but not the other and b) files with same relative path but differing contents:

# Using 'diff'
$ diff -x .DS_Store -qr dir1 dir2
$ diff -x '*.pyc' -x '*~' -x .DS_Store -qr ~/repos/ecom/ecom ~/repos/ecom.orig/ecom 

# Using 'rsync'.  See the --itemize-changes option to decode output.
$ rsync -irlc --dry-run dir1 dir2

# Use 'rsync' with -d to ignore files present in dir2 but not in dir1
$ rsync -rlcvd --dry-run dir1 dir2

# Compare two repos
$ rsync --dry-run -rlcv --exclude __pycache__/ --exclude 'var/' --exclude '*.pyc' \
        --exclude '.DS_Store' --exclude '*~' --exclude media/ --exclude static-collect/ \
        ~/repos/ecom/ecom/  ~/repos/ecom.orig/ecom/

# Using 'git'
$ git diff --name-status   ~/repos/ecom/ecom  ~/repos/ecom.orig/ecom
$ git diff --name-status   ~/repos/ecom/ecom  ~/repos/ecom.orig/ecom \
           | egrep -v '/media/|/var/|/static-collect/|.DS_Store|__pycache__'

Git

git-log

List commits:

# one commit per line
# with date, hash, comments
$ git log --date=short --format='%cd %h %s' 
# with date, hash, abbreviated comments
$ git log --date=short --format='%cd %h %<(70,trunc)%s' 
# with super short date format: YYMMDD
$ git log --date=format:'%g%m%d' --format='%cd %h %<(70,trunc)%s' 

# graph commit history, stats on changes to files
$ git log --date=short --graph --stat --stat-graph-width=20

# print number of commits per day
$ git log --date=format:'%g%m%d'| cut -d' ' -f 1 | uniq -c

List commits in develop but not in master:

$ git log develop --not master
$ git log master..develop

git-diff

All files changed between commits

$ git diff --name-only 23ea455 8bd2a33

git-branch

Rename both local and remote instances of a branch SO:

# rename local branch to new name
$ git branch -m old_name new_name

# delete old_branch on remote - where <remote> is, e.g, origin
$ git push <remote> --delete old_name

# push the new branch to remote
$ git push <remote> new_name

Note that if someone else has a local copy of the repo and they do a fetch after the above rename, their repo will contain one branch with the new name and on branch with the old name. They will need to delete their local copy of the branch with the old name.

Two branches: master and develop. Local and remote master are in sync. Local develop and remote develop have diverged significantly. I want to use the local develop to create a new branch named legacy and push that to remote, without damaging develop on the remote.

# rename the branch locally
$ git branch -m develop legacy

# push local legacy to a new remote branch
$ git push -u origin legacy

# confirm renamed branch is tracking new branch on remote
$ git branch -vv
  * legacy 51f0bb9 [origin/legacy] 2
    master d85b03c [origin/master] 1

# create a local develop branch using contents from remote
$ git checkout -b develop origin/develop

# confirm all branches now OK
$ git branch -vv
  * develop 51f0bb9 [origin/develop] 2
    legacy  51f0bb9 [origin/legacy] 2
    master  d85b03c [origin/master] 1   

Rename just a remote branch SO:

$ git push <remote> <remote>/<old_name>:refs/heads/<new_name> :<old_name>

gitk

Visualize your tree:

$ gitk --all --date-order

Use a local bare tree to fix problem. Create new local and remote branch named 'legacy', which contains contents of current local branch 'develop'.

$ cd ~/tmp
$ cp -r ~/repos/ecom ecom          # source repo
$ git clone ecom bitb --bare       # target bare repo
$ cd ecom
$ git checkout master
$ git remote add bitb ../bitb      # add bare repo as remote to source repo
$ git remote -v                    # confirm added properly
$ git branch -m develop legacy     # rename local branch
$ git push bitb legacy             # push renamed branch to remote
$ git fetch bitb
$ git checkout -b develop bitb/develop   # create new local branch

Shell Commands

grep

grep for text matching an extended regex in all python files in the current directory and below:

$ egrep 'this|that|whatever' -r --include='*.py' .

Other useful options:

            -l  - only print names of files with matches
            -o  - only print part of line matching regex
            -i  - ignore case in both the pattern and the input files
            -n  - print line numbers of matches
            -H  - print filename with each match
--exclude=GLOB  - exlude files matching GLOB