Git
Git Basics
Basics
clone a repository
git clone git@github.com:entorb/rememberthemilk.git
perform a commit
git add . git commit -m "my commit message" git push
Git Settings
!!! End of Line !!!
Force Git for Windows to use Linux end of line: LF (\n) instead of CRLF (\r\n)
git config --global core.autocrlf false git config --global core.eol lf
To use git to fix bad line endings, add a .gitattributes file to the repo with this contents:
* text eol=lf
colorful output
git config color.ui true
log: one line per commit
git config format.pretty oneline
Branching
# create new branch git checkout -b history-change # del branch git checkout main git branch -d history-change
Rename branch master to main
1. at github.com in the settings of the repo, rename the default branch name, for example at https://github.com/entorb/tools/settings/branches
2. update in local repo
git branch -m master main git fetch origin git branch -u origin/main main git remote set-head origin -a
3. set default branch name in local git
git config --global init.defaultBranch main
History
Reports
Git Log
git log git log --pretty=oneline --abbrev-commit # list commits including the change summary, e.g. 1 file changed, 16 insertions(+), 2 deletions(-) git log --date=short --pretty=format:"%cd %h %s" --shortstat
Git Rev-list
# Get the total commits by week git rev-list --count HEAD --since=4.week git rev-list --count main --since="Dec 1 2021" --before="Jan 3 2022"
Report of merges
var1 git --no-pager log --merges --pretty=format:'MyRepoName %cs %ae %s' | grep -v 'dependabot' >> ../git-merge-report.csv var2 git --no-pager log --grep='#' --pretty=format:'MyRepoName %cs %ae %s' --after 2022-01-01 >> ../git-merge-report.csv # note: in one repo the '--merges' flag did not find all merge PRs, so using --grep='#' instead
Checking History
Display all commits that modified a certain file
git log --no-decorate --pretty=format:"%h%x09%ad%x09%an%x09%s" --date=iso -- data/de-districts/de-district_timeseries-02000.tsv # %x09 : tab
Modifiying History
Merge 2 repos
see https://github.com/entorb/tools/blob/main/git-tools/git-merge-2-repos.cmd
delete a dir from historiy using git-filter-repo
preferred as of 2022 history cleanup using git-filter-repo
git clone xxx cd xxx # backup .git/config cp .git/config ../config python3 ../git-filter-repo.py --prune-empty always --invert-paths --path draft --path old --path maps/out # restore .git/config cp ../config .git/config git push -f
remove certain files matching a glob from history
python3 ../git-filter-repo.py --prune-empty always --invert-paths --path-glob "data/*/*.json"
delete a dir from historiy using bfg
note: better use git-filter-rep (see above)
using bfg
https://github.com/entorb/tools/blob/main/git-tools/git-bfg-cleanup-delete-history-of-dir.cmd git reflog expire --expire=now --all git gc --prune=now --aggressive
delete complete commits history
First Method from [1]
# Check out to a temporary branch: git checkout --orphan TEMP_BRANCH # Add all the files: git add -A # Commit the changes: git commit -am "Initial commit" # Delete the old branch: git branch -D main # Rename the temporary branch to main: git branch -m main # Finally, force update to our repository: git push -f origin main
Second Method via "deleting .git folder" also from [2]
# Clone the project, e.g. `myproject` is my project repository: git clone https://github/heiswayi/myproject.git # Since all of the commits history are in the `.git` folder, we have to remove it: cd myproject # And delete the `.git` folder: rm -rf .git # Now, re-initialize the repository: git init git remote add origin https://github.com/heiswayi/myproject.git git remote -v # Add all the files and commit the changes: git add --all git commit -am "Initial commit" # Force push update to the main branch of our project repository: git push -f origin main
Alternative method:
https://www.willandskill.se/en/deleting-your-git-commit-history-without-removing-repo-on-github-bitbucket/
Hacks
Cleanup
Remove branch not (any more) on main
prunes tracking branches not on the remote. from https://stackoverflow.com/posts/28464339/timeline
git remote prune origin
list branches that have been merged into the current branch.
git branch --merged
Reverting
reset to a commit
get hash of commit git log --oneline git reset --hard HEAD~1 # git push -f
revert a commit
get hash of commit git log --oneline git revert <commit hash> # git push -f
Reset branch to remote branch
from [3] Setting your branch to exactly match the remote branch can be done in two steps:
git fetch origin git reset --hard origin/main # git push -f
Fixing/Overwriting authors/emails
list authors
git shortlog -sn --all git log --pretty --author="my@mail.com"
perform the history rewrite using global git config (from https://stackoverflow.com/questions/750172/how-do-i-change-the-author-and-committer-name-email-for-multiple-commits/1320317#1320317)
git rebase -r --root --exec "git commit --amend --no-edit --reset-author"
Squashing
Squash last 3 commits
git reset --soft HEAD~3 && git commit
revert local git to remote repository
from [4]
git reset --hard HEAD git clean -f -d git pull
GIT Commit to an existing Tag
from https://gist.github.com/danielestevez/2044589
1) Create a branch with the tag git branch {tagname}-branch {tagname} git checkout {tagname}-branch 2) Include the fix manually if it's just a change .... git add . git ci -m "Fix included" or cherry-pick the commit, whatever is easier git cherry-pick {num_commit} 3) Delete and recreate the tag locally git tag -d {tagname} git tag {tagname} 4) Delete and recreate the tag remotely git push origin :{tagname} // deletes original remote tag git push origin {tagname} // creates new remote tag 5) Update local repository with the updated tag (suggestion by @wyattis) git fetch --tags This is based on https://gist.github.com/739288 thanks to nickfloyd for it
Chmod
set executable flag. see [5]
git update-index --chmod=+x file
Error handling
Error:
git pull --tags origin main [rejected] ... (would clobber existing tag)
Fixed by updating local tags with remote tags
git fetch --tags -f
Tag handling
Delete a tag locally
git tag -d myTag
Delete a tag remotely
git push --delete origin myTag
Clean up via Garbage Collector
git reflog expire --expire=now --all git gc --prune=now --aggressive
Scripts
Re-apply .gitignore
see https://github.com/entorb/tools/blob/main/git-tools/git-gitignore-reapply.cmd
pull on all repos
for D in $(ls -d */); do echo === $D === cd $D # git status current_branch=$(git branch --show-current) if [ "$current_branch" != "master" ] && [ "$current_branch" != "main" ]; then echo "branch was: $current_branch" git checkout main if [ $(git branch --show-current) != "main" ]; then git checkout master fi fi git pull --force cd .. done read -p "Enter to close"
revert on all repos
for D in $(ls -d */); do echo === $D === cd $D current_branch=$(git branch --show-current) if [ "$current_branch" != "master" ] && [ "$current_branch" != "main" ]; then echo "branch was: $current_branch" git checkout main if [ $(git branch --show-current) != "main" ]; then git checkout master fi fi git fetch origin git reset --hard origin/master git pull cd .. done read -p "Enter to close"
GitHub.com Tipps
create PR for another fork
- on github.com propose an edit for 1 file
- this creates a branch in our repo based on the fork, called patch-1 or similar
- rename the branch at `github.com/<your name>/<your repo>/branches/yours`
- now you can locally pull from your main to fetch the new fork and locally add more modifications
- I suggest keeping "unmodified" base-branches of other forks, so easily create new PRs and branches based on them
- to update the fork from he fork's main, use github.com
Alternative without GitHub tools: copy commit from partent repo to forked repo
git fetch upstream # Create new branch git checkout -b copy-commit-branch git cherry-pick <commit-hash> # Resolve conflicts (if any): git cherry-pick --continue git push origin copy-commit-branch # Finally create a pull request
Notes of 2020
very nice tutorial: git - Der einfache Einstieg
Old notes
git init # create an empty git repository in the current folder # set some settings git config --global user.name "Torben Menke" git config --global user.email "torben.menke@XXX.de" git config --global color.ui auto git config -l # shows configuration git add somefile.txt # one file git add somefolder # one folder git add . # all git commit git commit -a -m "message" # commit all, message="message" git pull ssh://tmenke@[IP]/[PATH] main # edit # commit git push ssh://tmenke@[IP]/[PATH] main git log git log --pretty=oneline --abbrev-commit