Git

From Torben's Wiki


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

[6] [7]

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