Skip to content

Instantly share code, notes, and snippets.

@iegik
Last active February 19, 2025 09:28
Show Gist options
  • Save iegik/14695af20faba5dbbd40b2d8bdfe38c9 to your computer and use it in GitHub Desktop.
Save iegik/14695af20faba5dbbd40b2d8bdfe38c9 to your computer and use it in GitHub Desktop.
Git configuration and aliases
{
"extends": [
"@commitlint/config-conventional"
],
"parserOpts": {
"headerPattern": "/^(\\w*)\\((\\w*)\\): (\\w*)\\s(.*)$/",
"headerCorrespondence": [
"type",
"scope",
"ticket",
"subject"
]
},
"formatter": "@commitlint/format",
"rules": {
"subject-case": [
2,
"always",
"sentence-case"
],
"subject-empty": [
2,
"never"
],
"subject-full-stop": [
2,
"never",
"."
],
"type-case": [
2,
"always",
"lower-case"
],
"type-empty": [
2,
"never"
],
"type-enum": [
2,
"always",
[
"build",
"chore",
"ci",
"docs",
"feat",
"fix",
"perf",
"refactor",
"revert",
"style",
"test"
]
]
},
"prompt": {
"questions": {
"type": {
"description": "Select the type of change that you're committing",
"enum": {
"feat": {
"description": "A new feature",
"title": "Features",
"emoji": "✨"
},
"fix": { "description": "A bug fix', \"title\": 'Bug Fixes', \"emoji\": '🐛"
},
"docs": {
"description": "Documentation only changes",
"title": "Documentation",
"emoji": "📚"
},
"style": {
"description": "Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)",
"title": "Styles",
"emoji": "💎"
},
"refactor": {
"description": "A code change that neither fixes a bug nor adds a feature",
"title": "Code Refactoring",
"emoji": "📦"
},
"perf": {
"description": "A code change that improves performance",
"title": "Performance Improvements",
"emoji": "🚀"
},
"test": {
"description": "Adding missing tests or correcting existing tests",
"title": "Tests",
"emoji": "🚨"
},
"build": {
"description": "Changes that affect the build system or external dependencies (example \"scopes\": gulp, broccoli, npm)",
"title": "Builds",
"emoji": "🛠"
},
"ci": {
"description": "Changes to our CI configuration files and scripts (example \"scopes\": Travis, Circle, BrowserStack, SauceLabs)",
"title": "Continuous Integrations",
"emoji": "⚙️"
},
"chore": {
"description": "Other changes that don't modify src or test files",
"title": "Chores",
"emoji": "♻️"
},
"revert": {
"description": "Reverts a previous commit",
"title": "Reverts",
"emoji": "🗑"
}
}
},
"scope": {
"description": "What is the scope of this change (e.g. component or file name)"
},
"subject": {
"description": "Write a short, imperative tense description of the change"
},
"body": { "description": "Provide a longer description of the change"
},
"isBreaking": { "description": "Are there any breaking changes?"
},
"breakingBody": {
"description": "A BREAKING CHANGE commit requires a body. Please enter a longer description of the commit itself"
},
"breaking": { "description": "Describe the breaking changes"
},
"isIssueAffected": { "description": "Does this change affect any open issues?"
},
"issuesBody": {
"description": "If issues are closed, the commit requires a body. Please enter a longer description of the commit itself"
},
"issues": {
"description": "Add issue references (e.g. \"fix #123\",\"re #123\".)"
}
}
}
}
[user]
name = John Smith
email = [email protected]
[filter "lfs"]
clean = git lfs clean %f
smudge = git lfs smudge %f
required = true
[core]
whitespace = cr-at-eol
[merge]
tool = winmerge
[mergetool]
prompt = false
keepBackup = false
keepTemporaries = false
[mergetool "winmerge"]
name = WinMerge
trustExitCode = true
cmd = "/c/Program\\ Files/WinMerge/WinMergeU.exe" -u -e -dl \"Local\" -dr \"Remote\" $LOCAL $REMOTE $MERGED
[diff]
tool = winmerge
[difftool "winmerge"]
name = WinMerge
trustExitCode = true
cmd = "/c/Program\\ Files/WinMerge/WinMergeU.exe" -u -e $LOCAL $REMOTE
# alias {{{
[alias]
# basic {{{
st = status -s
cl = clone
ci = commit
co = checkout
br = branch
r = reset
cp = cherry-pick
gr = grep -Ii
# }}}
# tweak defaults {{{
diff = diff --word-diff
branch = branch -ra
grep = grep -Ii
bra = branch -ra
ai = add --interactive
# grep on filename
f = "!git ls-files | grep -i"
# }}}
# commit {{{
cm = commit -m
cma = commit -a -m
ca = commit --amend
amend = commit --amend
caa = commit -a --amend -C HEAD
# }}}
# log commands {{{
ls = log --pretty=format:"%C(green)%h\\ %C(yellow)[%ad]%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --date=relative
ll = log --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --numstat
lc = "!f() { git ll "$1"^.."$1"; }; f"
lnc = log --pretty=format:"%h\\ %s\\ [%cn]"
fl = log -u
filelog = log -u
# }}}
# diff {{{
d = diff --word-diff
dc = diff --cached
# diff last commit
dlc = diff --cached HEAD^
dr = "!f() { git diff -w "$1"^.."$1"; }; f"
diffr = "!f() { git diff "$1"^.."$1"; }; f"
# }}}
# reset commands {{{
r1 = reset HEAD^
r2 = reset HEAD^^
rh = reset --hard
rh1 = reset HEAD^ --hard
rh2 = reset HEAD^^ --hard
# }}}
# git svn {{{
svnr = svn rebase
svnd = svn dcommit
svnl = svn log --oneline --show-commit
# }}}
# stash {{{
sl = stash list
sa = stash apply
ss = stash save
# }}}
# assume aliases {{{
assume = update-index --assume-unchanged
unassume = update-index --no-assume-unchanged
# show assumed files
assumed = "!git ls-files -v | grep ^h | cut -c 3-"
# unassume all the assumed files
unassumeall = "!git assumed | xargs git update-index --no-assume-unchanged"
assumeall = "!git st -s | awk {'print $2'} | xargs git assume"
# }}}
# subtree {{{
# add
sba = "!f() { git subtree add --prefix $2 $1 master --squash; }; f"
# update/pull
sbu = "!f() { git subtree pull --prefix $2 $1 master --squash; }; f"
# }}}
# various useful {{{
# last tag created
lasttag = describe --tags --abbrev=0
lt = describe --tags --abbrev=0
# conflict/merges
ours = "!f() { git co --ours $@ && git add $@; }; f"
theirs = "!f() { git co --theirs $@ && git add $@; }; f"
#list remotes
rem="!git config -l | grep remote.*url | tail -n +2"
#apply patch from other local repo
lap = "!f() { git --git-dir=$1 format-patch -k -1 --stdout $2 | git am -3 -k; }; f"
#open files edited in last commit
last = "!gvim $(git show HEAD --format="" --name-only | xargs)"
# initial empty commit
empty = "!git commit -am\"[empty] Initial commit\" --allow-empty"
# list all aliases
la = "!git config -l | grep alias | cut -c 7-"
# }}}
# convoluted aliases {{{
# grep from root folder
gra = "!f() { A=$(pwd) && TOPLEVEL=$(git rev-parse --show-toplevel) && cd $TOPLEVEL && git grep --full-name -In $1 | xargs -I{} echo $TOPLEVEL/{} && cd $A; }; f"
#rename branch tree to done-
done = "!f() { git branch | grep "$1" | cut -c 3- | grep -v done | xargs -I{} git branch -m {} done-{}; }; f"
#add bitbucket remote
ra = "!f() { git remote add $1 https://bitbucket.org/$2.git; }; f"
# }}}
# remove merged branches
cc = "!git branch --merged | grep -v 'master\\|*' | awk '{print \"git branch -d \"$1}' | bash"
st-files = !git diff --name-status origin/master..HEAD # show changed files in HEAD
twig-lint = !git st-files | grep .tpl | awk '{print \"php ~/.composer/vendor/asm89/twig-lint/bin/twig-lint lint \"$2}' | bash # applies asm89/twig-lint rules for changed files in HEAD
eslint = !git st-files | grep .js | awk '{print \"eslint --fix \"$2}' | bash # applies eslint rules for changed files in HEAD
unstage = reset HEAD --
lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %Cblue<%an>%Creset' --abbrev-commit --date=relative --all
credits = shortlog -s -n
# }}}

Setup Git

ssh-keygen -t ed25519 -C "[email protected]"
eval "$(ssh-agent -s)"
ssh-add

Get fingerprint

ssh-keygen -l -f ~/.ssh/id_rsa.pub

// Old
ssh-keygen -l -E md5 -f ~/.ssh/id_rsa.pub

LFS

brew install git-lfs

export PATH=/opt/homebrew/Cellar/git-lfs/*/bin:$PATH

git lfs install

Issues

Turning of Tracking of Executable Bit Change

git config --local core.fileMode false

Turning of auto CLRF

git config --local core.autoclrf false

Rebasing

чтобы pull происходил через rebase: git config --global pull.rebase true

Autocomplete branches

https://medium.com/@oliverspryn/adding-git-completion-to-zsh-60f3b0e7ffbc

mkdir -p ~/.zsh
cd ~/.zsh

# Download the scripts
curl -o git-completion.bash https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash
curl -o _git https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.zsh

open ~/.zshrc:

# Load Git completion
zstyle ':completion:*:*:git:*' script ~/.zsh/git-completion.bash
fpath=(~/.zsh $fpath)

autoload -Uz compinit && compinit

Git aliases

Common aliases used:

open ~/.gitconfig:

[alias]
    s = status -s
    co = checkout
    br = branch
    cp = cherry-pick
    last = log -1 HEAD
    amend = commit --amend --no-edit
    l = log --oneline -n 10

open ~/.bash_aliases:

alias g=git

Effective commit messages

  • avoid trivial commit messages (fix)
  • describe "why" & "what" reather then "how"
  • include relevant feature/bug ticket links
  • could include the change "type" (feature/bug/chore/engeneering)
  • keep 1st line less than 50 chars
  • leave 2nd line blank
  • wrap lines in commit body around 70 chars
  • clean breaks between lines in the commit body
  • treat your commit history as an novel documenting the project's history
  • [WIP] flags will block pull/merge requests
ISSUE-123/bug: [WIP] Blinking dot within input

Inputs became much nicer, without glitches
and more responsive
http://tracker.local/issue/ISSUE-123

Reports:

Daily standup's:

git standup

Work done report:

git log --pretty=format:"%ad - %an: %s" --after="2016-01-31" --until="2017-03-10" --author="John Doe"

Changing a commit message

git commit --amend

https://help.github.com/articles/changing-a-commit-message/

Rename locally and remote

You just have to create a new local branch with the desired name, push it to your remote, and then delete the old remote branch:

git branch new-branch-name origin/old-branch-name
git push origin --set-upstream new-branch-name
git push origin :old-branch-name

Then, to see the old branch name, each client of the repository would have to do:

git fetch origin
git remote prune origin

NOTE: If your old branch is your main branch, you should change your main branch settings. Otherwise, when you run $ git push origin :old-branch-name, you'll get the error "deletion of the current branch prohibited".

http://stackoverflow.com/questions/4753888/git-renaming-branches-remotely

How to write commit messages

// commitlint.config.js
module.exports = {
  extends: ["@commitlint/config-conventional"],
};

http://chris.beams.io/posts/git-commit/

Remove sensitive data

https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository

Move the most recent commit(s) to a new branch

Moving to an existing branch

git checkout existingbranch
git merge branchToMoveCommitFrom
git checkout branchToMoveCommitFrom
git reset --hard HEAD~3 # Go back 3 commits. You *will* lose uncommitted work.
git checkout existingbranch

Moving to a new branch

WARNING: This method works because you are creating a new branch with the first command: git branch newbranch. If you want to move commits to an existing branch you need to merge your changes into the existing branch before executing git reset --hard HEAD~3 (see Moving to an existing branch above). If you don't merge your changes first, they will be lost.

# Note: Any changes not committed will be lost.
git branch newbranch      # Create a new branch, saving the desired commits
git checkout master       # checkout master, this is the place you want to go back
git reset --hard HEAD~3   # Move master back by 3 commits (Make sure you know how many commits you need to go back)
git checkout newbranch    # Go to the new branch that still has the desired commits

https://stackoverflow.com/questions/1628563/move-the-most-recent-commits-to-a-new-branch-with-git

Git Clean-up in Local and Remote Branches, Repositories

http://railsware.com/blog/2014/08/11/git-housekeeping-tutorial-clean-up-outdated-branches-in-local-and-remote-repositories/

Undo checkout

For a single file:

git checkout HEAD /path/to/file

For the entire repository working copy:

git reset --hard HEAD

And if that doesn't work, then you can look in the reflog to find your old head SHA and reset to that:

git reflog
git reset --hard <sha from reflog>

https://stackoverflow.com/questions/3601911/how-do-i-undo-a-checkout-in-git

Recover corrupted blob

http://git.kernel.org/cgit/git/git.git/tree/Documentation/howto/recover-corrupted-blob-object.txt?id=HEAD

Successful branch model

brew install git-flow

git flow init|feature|release|hotfix|support

https://nvie.com/posts/a-successful-git-branching-model/

Syncing a fork

git fetch upstream
git checkout main
git merge upstream/main

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

Squash latest commits into one

git rebase -i HEAD~3

pick|squash|fixup|edit|drop

https://www.devroom.io/2011/07/05/git-squash-your-latests-commits-into-one/

How to create tags

First, make sure that the tag exists locally by doing

# --all will fetch all the remotes.
# --tags will fetch all tags as well
git fetch --all --tags --prune

Then check out the tag by running

$ git checkout tags/<tag_name> -b <branch_name>

In this sample you have 2 tags version 1.0 & version 1.1 you can check them out with any of the following:

$ git checkout A  ...
$ git checkout version 1.0  ...
$ git checkout tags/version 1.0  ...

How to see the list of all tags?

# list all tags
$ git tag

# list all tags with given pattern ex: v-
$ git tag --list 'v-*'

How to create tags?

# lightweight tag 
$ git tag v1.0

# annotated tag
$ git tag -a v1.0

How to delete tags?

  • $ git tag -d <tag_name> - Delete a local tag
  • git push --delete origin <tag name> - Delete remote tags

How to clone a specific tag?

  • Option 1:
# Update the local git repo with the latest tags from all remotes
$ git fetch --all

# checkout the specific tag
$ git checkout tags/<tag> -b <branch>
  • Option 2:
# Clone a specific tag name using git clone 
$ git clone <url> --branch=<tag_name>

How to push tags?

  • git push --tags
  • git push refs/tags --tags - It's recommended to use refs/tags since sometimes tags can have the same name as your branches and a simple git push will push the branch instead of the tag
  • git push --follow-tags - This flag --follow-tags pushes both commits and only tags that are both:
    • Annotated tags (so you can skip local/temp build tags)
    • Reachable tags (an ancestor) from the current branch (located on the history)
  • git describe --tags

From Git 2.4 you can set it using configuration $ git config --global push.followTags true

https://stackoverflow.com/questions/35979642/what-is-git-tag-how-to-create-tags-how-to-checkout-git-remote-tags

How to list all files in commit

Preferred Way (because it's a plumbing command; meant to be programmatic):

$ git diff-tree --no-commit-id --name-only bd61ad98 -r

Another Way (less preferred for scripts, because it's a porcelain command; meant to be user-facing)

$ git show --pretty="" --name-only bd61ad98

  • The --no-commit-id suppresses the commit ID output.
  • The --pretty argument specifies an empty format string to avoid the cruft at the beginning.
  • The --name-only argument shows only the file names that were affected (Thanks Hank). Use --name-status instead, if you want to see what happened to each file (Deleted, Modified, Added)
  • The -r argument is to recurse into sub-trees

https://stackoverflow.com/questions/424071/how-do-i-list-all-the-files-in-a-commit

Commit without pre-commit hook

$ git commit . -m 'quick fix' --no-verify

https://ma.ttias.be/git-commit-without-pre-commit-hook/#:~:text=Quick%20tip%20if%20you%20want,get%20a%20commit%20out%20there.&text=To%20get%20your%20commit%20through,the%20--no-verify%20option.&text=Voila%2C%20without%20pre-commit%20hooks%20running!

Changesets

npx changeset init
npx changeset // add feature/fix
npx changeset version // make release
npx changeset publish // This will run npm publish in each package that is of a later version than the one currently listed on npm.

https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md#creating-changesets

Submodules not work

git submodule init
git submodule update --recursive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment