Git

From Torben's Wiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.


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

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