Showing posts with label Vcs. Show all posts
Showing posts with label Vcs. Show all posts

Friday, 29 March 2019

Quickly search your Git log using wildcards and shell function

Imagine you got a Git repository with a long history - equivalent to log - and you want find a changeset with a comment containing a word or some words and you want to get the commit SHA to quickly cherry pick that commit to your target branch. This is easier using Azure Devops or some tool, but how to quickly search the log. First we define a search log shell function inside our git config file .gitconfig :

searchlog = "!f() { git --no-pager log --color-words --all --decorate --graph -i --grep \"$1\";  }; f"

Now we can search the log quickly using a wildcard:
git searchlog "visning.*av.*nåtidslinje.*"
We separate our search words with the .* regex syntax and we can search our git log for multiple keywords quickly and get a nice presentation of commits with commit messages matching our log. And now we have a quick way to find our Git commits through the log and the command line to overcome our needly in the haystack scenario.

Sunday, 4 November 2018

Closing branches in Git

Git unlike Mercurial has no builtin support for closing branches. This leads to a proliferation of branches and running git branch -a to view remote branches or git branch will show ever more branches. Actually, closing a branch in Git can be supported through the use of tags. We decide to keep the tag for future use, so that we can use it to check out a new branch from this tag. Another way would of course be to just delete a brach local and/or remote, but that is not the same as closing a branch. Closing a branch in Mercurial still makes it possible to reopen it again for later work. Anyways, in this article, I will show two aliases which can be used to close a branch, either both local and remote or just remote. Put the following into the [alias] section of your .gitConfig file:

closebranch = "!w() { echo Attempting to close local and remote branch: $1 Processing...; echo Checking the branch $1 out..; git checkout $1; echo Trying to create a new tag archive/$1; git tag archive/\"$1\"; git push origin archive/\"$1\"; echo Deleting the local branch $1; git branch -d $1;  echo Deleting the remote branch $1; git push origin --delete $1; echo Done. To restore the closed branch later, enter: git checkout -b MyNewBranch archive/\"$1\"; }; w"

closebranchpassive = "!w() { echo Attempting to close local and remote branch: $1 Processing...; echo Checking the branch $1 out..; git checkout $1; echo Trying to create a new tag archive/$1; git tag archive/\"$1\"; git push origin archive/$1; echo Deleting the local branch $1;   echo Deleting the remote branch $1;  echo Done. To restore the closed branch later, enter: git checkout -b MyNewBranch archive/\"$1\"; }; w"

closeremotebranch =  "!w() { echo Attempting to close remote branch: $1 Processing...; echo Checking the branch $1 out..; git checkout $1;  echo Trying to create a new tag archive/$1; git tag archive/\"$1\"; git push origin archive/\"$1\"; echo Deleting the remote branch $1; git push origin --delete $1; echo Done. To restore the closed branch later, enter: git checkout -b MyNewBranch archive/\"$1\"; }; w"

What we do here is the following:
  • Check out the branch to close
  • Tag this branch as archive/branchname
  • Important - push the tag the remote e.g. origin in the provided aliased commands above
  • (Delete the local branch)
  • Delete the remote branch
  • Display a friendly output message how to restore the branch later through a tag
What we use here is a shell function in each alias. This allows us to do multiple commands in Git through a simple aliased command. Say you want to close a local and remote branch called MyBranchToBeClosed. Just enter: git closebranch MyBranchToBeClosed If you just want to close the remote branch and keep the local one, enter: git closeremotebranch MyBranchToBeClosed To restore the branch MyBranchToBeClosed (which now is actually closed!) later, just enter: git checkout -b MyRestoredBranch archive/MyBranchToBeClosed This lets you keep old branch around as tags and not proliferate the branch listings. We however have moved the branch(es) over to tags prefixed with archive/ I wish Git was simpler to use sometimes so we did not have to use such hacks, closing branches should be easy.

Thursday, 6 September 2018

Some handy Git tips - show latest commits and searching the log and more

This article will present some tips around Git and how you can add functionality for showing the latest commits and search the log. I would like to search these aliased command to show you how they can ease your everyday use of Git from the commandline.

[alias]

glog = log --all --decorate --oneline --graph

glogf = log --all --decorate --oneline --graph --pretty=fuller

st = status

out      = !git fetch && git log FETCH_HEAD..

outgoing = !git fetch && git log FETCH_HEAD..

in       = !git fetch && git log ..FETCH_HEAD

incoming = !git fetch && git log ..FETCH_HEAD

com = "!w() { git commit --all --message \"$1\";  }; w"

undopush = "!w() { git revert HEAD~\"$1\"..HEAD;  }; w"

searchlog = "!f() { git --no-pager log --color-words --all --decorate --graph -i --grep \"$1\";  }; f"

branches =  branch --verbose --sort=-committerdate --format '%(HEAD)%(color:yellow)%(refname:short)%(color:reset) -%(color:red)%(objectname:short)%(color:reset) - %(contents:subject) -%(authorname) (%(color:green)%(committerdate:relative)%(color:reset))'

allbranches = "!g() { git branch --all --verbose --sort=-committerdate --format '%(HEAD) %(color:yellow)%(refname:short)%(color:reset) -%(color:red)%(objectname:short)%(color:reset) - %(contents:subject) -%(authorname) (%(color:green)%(committerdate:relative)%(color:reset))' --color=always | less -R;  }; g"
verify = fsck
clearlocal = clean -fd && git reset 
stash-unapply = !git stash show -p | git apply -R 
lgb = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset%n' --abbrev-commit --date=relative --branches tree = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset%n' --abbrev-commit --date=relative --branches alltree = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset%n' --date=relative --branches --all
latest = "!f() { echo "Latest \"${1:-11}\" commits accross all branches:"; git log  --abbrev-commit --date=relative --branches --all --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset%n' -n ${1:-11};  } ; f"
add-commit = !git add -A && git commit
showconfig = config --global -e

[merge]
tool = kdiff3

[mergetool "kdiff3"]
cmd = \"C:\\\\Program Files\\\\KDiff3\\\\kdiff3\" $BASE $LOCAL $REMOTE -o $MERGED [core]
editor = 'c:/program files/sublime text 3/subl.exe' -w

[core]
editor = 'c:/Program Files/Sublime Text 3/sublime_text.exe'

The best aliases are how you set up Sublime Text 3 as the Git editor and also how you can show the latest commits. The latest commits use a parametrized shell function. I set the default value to 11 in this case, if you do not give a parameter. You can for example show the latest 2 commits by typing: git latest 2
latest = "!f() { echo "Latest \"${1:-11}\" commits accross all branches:"; git log  --abbrev-commit --date=relative --branches --all --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset%n' -n ${1:-11};  } ; f"
Note the use of a shell function and also that we refer to the first parameter as ${1} i bash shell script, with a :-11 to set the first param as 11. The syntax is ${n:-p} where n is the nth parameter (not starting with zero!) and p is the default value. A special syntax, but that is how bash works. Also note that a git alias with a shell function can do multiple functions, separated with semi-colon ;. The searchlog alias / shell function is also handy:
searchlog = "!f() { git --no-pager log --color-words --all --decorate --graph -i --grep \"$1\";  }; f"
Also, multiple aliases here are similar to Mercurial's in and out commands to detect incoming pushed commits and outgoing local commits. Happy Git-ing!