Git operators#
HEAD^
is one commit before HEADHEAD~4
is four commits before HEAD
Change remote of an existing repo#
Check current urls:
git remote -v
Switch urls:
git remote set-url origin NEWURL
Compare change
git remote -v
Push to new remote
git push -u origin master
Run git command over all subdirectories#
find . -maxdepth 1 -type d -exec git --git-dir={}/.git --work-tree=$PWD/{} pull \;
Proxy settings#
git config --global http.proxy http://proxy.company.com:3128
or in .git/config
[http]
proxy = http://proxy.company.com:3128
or temporarily as command line argument
-c http.proxy http://proxy.company.com:3128
Disable certificate validation#
git config --global http.sslVerify=false
or in .git/config
[http]
sslVerify = false
or temporarily as command line argument
-c http.sslVerify=false
Show the current branch#
git rev-parse --abbrev-ref HEAD
Use Github and Gitlab#
Use multiple remotes named differently#
git remote add github https://github.com/USER/repo.git
git push/pull origin
git push/pull github
When the origin is at github vice versa.
Single remote with multiple targets#
git remote set-url –add origin https://github.com/USER/repo.git
git push/pull origin
When the origin is at Github vice versa. Now, origin will target Gitlab as well as Github remotes
Edit git config with editor#
git config [--global] --edit
Set git file endings to LF (msysgit)#
git config --global core.autocrlf false
git config --global core.eol lf
Debug git command#
GIT_CURL_VERBOSE=1 GIT_TRACE=1 git pull
even more output:
set -x; GIT_TRACE=2 GIT_CURL_VERBOSE=2 GIT_TRACE_PERFORMANCE=2 GIT_TRACE_PACK_ACCESS=2 GIT_TRACE_PACKET=2 GIT_TRACE_PACKFILE=2 GIT_TRACE_SETUP=2 GIT_TRACE_SHALLOW=2 git pull origin master -v -v; set +x
List all repos a Github user is allowed to access#
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Small CLI script to list basic overview of our Github repositories
- Access and repositories are based upon the user's permissions
- Default output is a SingleTable (fancier) but ASCII Table is supported as well
- Show last commit only since a defined period of time to limit required API calls
Install dependencies with 'pip3 install --user PyGithub, terminaltables' or appropriate command
"""
__version__ = "1.0.0"
from datetime import datetime, timedelta
import argparse
from github import Github
from terminaltables import AsciiTable, SingleTable
def main(args):
""" entry point """
g = Github(args.token)
data = [['Name', 'URL', 'Tags', 'Branches', 'Last Commit']]
since = datetime.now() - timedelta(days=args.days)
for repo in g.get_user().get_repos():
# to see all the available attributes and methods
# print(dir(repo))
commits = repo.get_commits(since=since)
date = 'unknown'
author = 'unknown'
try:
if commits.totalCount > 0:
last_commit = commits[0]
date = last_commit.last_modified
author = last_commit.author.login
except:
pass # empty repo found ^^
name = repo.name
url = repo.clone_url
tags = []
for tag in repo.get_tags():
tags.append(tag.name)
branches = []
for branch in repo.get_branches():
branches.append(branch.name)
data.append([name, url, '\n'.join(tags), '\n'.join(branches), f"{date} by {author}"])
if (args.a):
table = AsciiTable(data)
else:
table = SingleTable(data)
table.inner_row_border = True
print(table.table)
if __name__ == "__main__":
""" Executed from the commandline"""
parser = argparse.ArgumentParser(description='Terminal Github Overview for Innio')
parser.add_argument('-t', '--token', action='store', required=True, help='your Github API token')
parser.add_argument('-d', '--days', action='store', type=int, default=1, help='list commits since x days')
parser.add_argument('-a', action='store_true', default=False, help='use simple ASCII table as output')
parser.add_argument('-v', action='version',version='%(prog)s (version {version})'.format(version=__version__))
args = parser.parse_args()
main(args)
Remove submodule#
How to remove a submodule from a git repository1
- Remove the relevant
.gitmodules
section git add .gitmodules
- Remove the relevant
.git/config
section git rm --cached /path/to/submodule
(no trailing slash)git commit -m "Remove submodule"
rm -rf /path/to/submodule
old mode 100755 new mode 100644#
git config core.filemode false
Integrating branches#
With merge#
git checkout feature
git merge master
This results in a merge commit and may pollute the commit log but it preserves history in contrast to rebase
With rebase#
Don’t do that on public branches where multiple devs are working on as this will rewrite the commit history according to your local branch!
git checkout feature
git rebase master
Delete branches#
git push -d <remote_name> <branch_name>
git branch -d <branch_name> # only delete a local branch
-D
forces the deletion when the branch is not merged in
# Delete local branches that do not exist on remote anymore
git remote prune origin
Delete tags#
# alternative approach
git push --delete origin <tag>
git tag -d <tag> # only delete local tag
Undo#
Undo public change#
Use case: After a git push
you realize a commit is wrong
Undo: git revert <SHA>
This will create a new commit that reverts the specified commit
Fix commit message#
Use case: Typo in commit message “before” git push
Undo: git commit --amend -m "Fixed commit message"
This will update and replace the most recent commit. Be aware that staged changes will be included as well so in order to just fix the commit message ensure that there are no staged changes.
Undo local change#
Use case: After editing local files nothing is working and you want to undo everything you have done.
Undo: git checkout -- <filename>
This will modify the file to a state known to git. Be aware that you cannot recover this as nothing was ever committed!
Reset local change#
Use case: You made local commits (not yet pushed) and you want to undo the last four commits without any leftovers.
Undo: git reset [--hard] <last good SHA>
This will rewind the history of your repo back to the specified SHA as if the commits never happened. By default, git reset
only removes the commits but not the content on disk. --hard
option will also remove the changes on disk.
Redo after undo local change#
Use case: After git reset --hard
you changed your mind and want the changes back
Undo: git reflog
This will show a list of times Use case HEAD
changed.
Wrong branch#
Use case: You made some commits accidenttally on master instead a feature branch.
Undo: git branch feature
, git reset --hard origin/master
, git checkout feature
This will
- create a branch named “feature” pointing to the most recent commit while still in master
- Rewinds master back to origin/master before your new commits while they still exist on “feature” branch
- Switch to the new “feature” branch with all the recent work
Branch in#
Use case: Branch named “feature” branch started from master but you realized that after syncing master with origin/master that master was far behind. Now commits on “feature” should start now instead of being behind.
Undo: git checkout feature
, git rebase master
(compare Integrate branches)
This will
- locate the common ancestor between “feature” and master
- reset “feature” to that ancestor while holding all commits in a temporary area
- advance “feature” to the end of master and replay all commits from the temporary area after master’s last commit
Mass undo/redo#
Use case: You have a dozen commits but only want some of them and the rest should disappear
Undo: git rebase -i <earlier SHA>
This will start rebase in interactive mode like above but before replaying any commits you have the chance to modify each commit.
pick
is the default action meaning the commit will be applied- to delete commits just delete the line
reword
to preserve the content of the commit and rewrite the commit message. Be aware that you cannot edit the message here as rebase ignores everything after the SHA column. After finishing rebasing you will be prompted for new messages.fixup
orsqash
to combine commits “upwards”. squash will create a new commit and ask for a new commit message. fixup will use the message from the first commit in the list.- reorder commits by changing the order before saving
Fix an earlier commit#
Use case: You forgot to include a file in an earlier commit. You haven’t pushed yet but it also is not the most recent commit (–amend won’t work)
Undo: git commit --sqash <SHA of the earlier commit>
, git rebae --autosqash -i <even earlier SHA>
This will
- create a new commit with a message like “squash! Earlier commit”
- launch an interactive rebase with any squash! (and fixup!) commits already paired to the commit target
Stop tracking a tracked file#
Use case: Accidenttaly, you added a wrong file to the repo
Undo: git rm --cached <filename>
This will remove the file from git but preserves the content on disk
Modify past commits#
Start the rebase at the last “good” commit
git rebase -i -p COMMITHASH
or start from the initial commit with
git rebase -i --root $tip
After this command a text editor will open. Edit the keywords at the beginning of the line, in this case edit
allows us to modify the commits. After saving the file the first commit to be edited will be selected. Now you can run e.g.
git commit --amend --author="Michael <allaman@rootknecht.net>" --no-edit
to modify the author. Then run
git rebase --continue
to go to the next marked commit. After rebasing run
git push --force-with-lease
to push your modifications.