Git #
I consider git on of the most important software ever created. It enabled people to work geographically distributed even without internet connection, with automated backups (every repo is potentially a repository backup). Because of this little tool, software could evolve faster than ever. Yes, we had other version control systems before git, but only with git (and mercurial) we could work efficiently remotelly and OFFLINE.
To update the local list (cache) of remote branches #
# To show all local and remote branches that (local) Git knows about:
git branch -a
# And to update it:
git remote update origin --prune
# Now you can see everything up to date with the origin
git branch -a
Or you can also do a git pull --all
to fetch from origin and update all your local branches.
git patch #
To generate a patch from the last 10 commits:
git format-patch -10 --stdout > mypatch.patch
Creat a patch from stashed changes:
git stash list
git stash show -p stash@{<number>} > mypatch.patch
From uncommited changes:
git diff > mypatch.patch
To apply a patch:
git apply mypatch.patch
git stash #
Everything is stashed in a stack. To reference it you can do stash@{n}
where n is the offset in the stack.
To stash you can do:
# stashes everything
git stash
# list what is stashed
git stash list
# apply the most recent stash and delete it
git stash pop # it's the same as doing git stash pop stash@{0}
# apply the second most recent stash and delete it
git stash pop stash@{1}
# apply the stashed content and does not delete it like pop does
git stash apply # it's the same as doing git stash apply stash@{0}
# you can set a description to stashed content
git stash save "message"
# you can view a summary of a stash
git stash show
# or to show the full diff
git stash show -p
Creating a branch from a stash #
git stash branch add-stylesheet stash@{1}
Cleaning up the stash #
git stash clear
#or
git stash drop # it will drop the stash@{0}
git-crypt #
Git crypt is just awesome. Not perfect, but awesome. It is very useful, despite of its limitations.
Before starting it #
Make sure you have the public gpg key installed:
# List gpg keys
gpg --list-keys
# List gpg secret keys
gpg --list-secret-keys
If you don’t have you can generate one with GPG.
Importing keybase keys to gpg #
# import keybase keys to gpg
keybase pgp export | gpg --import
# import private keys to gpg
keybase pgp export -s | gpg --allow-secret-key-import --import
Encrypting a git repository folder #
#initiate it
git-crypt init
#add the public key of the user
git-crypt add-gpg-user 5A3700C672440657ACF09DEFB146A056E9BACD36
Configuring the secret files:
In the .gitattributes
file you must do:
# Example
secretfile filter=git-crypt diff=git-crypt
*.key filter=git-crypt diff=git-crypt
secretdir/** filter=git-crypt diff=git-crypt
src/main/resources/*.yml filter=git-crypt diff=git-crypt
Showing encrypted files #
git-crypt status -e
Changing the author of the last commit #
git commit --amend --author="Eduardo Ivan Pichler <eduardo.pichler@myemail.com>" --no-edit
Changing the Author for global and local repositories #
git config --global user.name "Eduardo Ivan Pichler"
git config --global user.email "eduardo.pichler@myemail.com"
Or:
git config --local user.name "Eduardo Ivan Pichler"
git config --local user.email "eduardo.pichler@myemail.com"
Signing your git commits #
Just do git config commit.gpgsign true
in your repository.
To sign all commits by default in any local repository on your computer, run git config --global commit.gpgsign true
Pushing automatically after a commit #
You need to have an executable (chmod +x) file in .git/hooks/post-commit that contains the following:
#!/bin/sh
git push origin master
You can create it by doing:
echo "#!/bin/sh" >> .git/hooks/post-commit
echo "git push origin master" >> .git/hooks/post-commit
Software archeology with git #
See the author names #
git shortlog -sne | cut -f2 | sort
Count the number of commits per file #
Files with many commits can often, but not always, point to a design problem.
git log --no-merges --no-renames --numstat --pretty=format:"" -- **/*.java | cut -d$'\t' -f3 | grep -v '^$' | sort | uniq -c | sort
Search for commit activity per author #
git shortlog -ns -- **/*.java
Or, better:
git shortlog -ns . --since "5 month ago"
Search for awkward things #
Todos and fixmes:
git grep --perl-regexp "\/\/ *(todo|fixme)"
Commented code:
git grep --perl-regexp " \/\/.*(=|;)" -- *.java
Browse through the commit messages #
git log --pretty=format:"%h %s"
Count last changed line in each Java source code file per author #
find . -type d -name ".git" -prune -o -type f \( -iname "*.java" \) | xargs -n1 git blame -w -f -C -M --date=format:"|" | cut -d"|" -f 1 | cut -d"(" -f 2 | sed 's/\s*$//' | sort | uniq -c | sort
Search in the commit content #
git rev-list --all | xargs git grep \.stream\(\)
Or:
git grep stream\. $(git rev-list --all)
In git grep
you can have the line number by adding -n
.
Or :
git log -Gstream
You can add a -p
flag:
git log -p -Gstream
See more ways in this forum
Limiting to a subtree, for instance lib/util. Notice you need to pass it in both commands: #
git grep <regexp> $(git rev-list --all -- lib/util) -- lib/util
Search working tree for text matching regular expression regexp: #
git grep <regexp>
Search for a pattern only in the changed lines #
git diff --unified=0 | grep <pattern>
Search all revisions for text matching regular expression regexp: #
git grep \.stream\(\) $(git rev-list --all)
All the branches that contain a commit #
git branch -a --contains 8beeff00d
Getting more information about a commit #
You can then get more information like author, date, and diff using git show:
git show 6988bec26b1503d45eb0b2e8a4364afb87dde7af
All commits that cointain a regex #
git log --author=edu --pretty -G \.stream\(\)
git log --author=edu --pretty -G \.stream\(\) -- **/*Test.java
git log --author=edu --pretty -G \.stream\(\)