Git Notes
Generating SSH keys (copy paste from Github)
$ ssh-keygen -t ed25519 -C "your_email@example.com"
# legacy
# $ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
$ eval $(ssh-agent -s)
$ ssh-add ~/.ssh/id_rsa
$ cat ~/.ssh/id_rsa.pub
Commands easy to forget
$ git remote -v
$ git rebase -i branchname or commit hash
$ git log --stat
$ git log --graph
$ git checkout other-branch the/path/to/yourfile
$ git diff yourbranch otherbranch -- file
$ git merge --reset
Tags
Annotated (with message) and light-weight (no message).
$ git tag
$ git push origin tag_name
$ git show tag_name
$ git log -1 tag_name
Annoying line-ending differences
Checkout Windows-style, commit Unix-style
git config core.autocrlf true
Git will convert LF to CRLF when checking out text files. When committing text files, CRLF will be converted to LF. For cross-platform projects, this is the recommended setting on Windows.
Checkout as-is, commit Unix-style
git config core.autocrlf input
Git will not perform any conversion when checking out text files. When committing text files, CRLF
will be converted to LF
. For cross-platform projects this is the recommended setting on Unix.
Checkout as-is, commit as-is
git config core.autocrlf false
Git will not perform any conversions when checking out or committing text files. Choosing this option is not recommended for cross-platform projects.
Gitignore
To create a user .gitignore
and not global, do:
# go to your repo .git folder
$ cd <your-repo>/.git
# populate with your files/folders
$ nano .user_gitignore
# add it to your config
$ git config core.excludesfile .git/.user_gitignore
# you can see it is added
$ git config -l
To create a global .gitignore
, do:
# or where desired
$ git config --global core.excludesfile ~/.global_gitignore
Using HEAD^ and HEAD~
Basically HEAD^
is doing a BFS traversal while HEAD~
only recognizes the first parent but can select the leaves using the caret e.g. H = A^^^2 = A~2^2
G H I J
\ / \ /
D E F
\ | / \
\ | / |
\|/ |
B C
\ /
\ /
A
A = = A^0
B = A^ = A^1 = A~1
C = A^2 = A^2
D = A^^ = A^1^1 = A~2
E = B^2 = A^^2
F = B^3 = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2 = B^^2 = A^^^2 = A~2^2
I = F^ = B^3^ = A^^3^
J = F^2 = B^3^2 = A^^3^2
Using multiple SSH keys
Useful if you have bitbucket, github etc. and want to use different ssh keys instead of sharing them - for security inconvenience reasons
Generate a ssh key and add it to your account e.g. bitbucket_rsa
Edit your
~/.ssh/config
:# ~/.ssh/config # Github Host github-foobar HostName github.com User git IdentityFile ~/.ssh/id_rsa # Bitbucket Host bitbucket-deadbeef HostName bitbucket.com User git IdentityFile ~/.ssh/bitbucket_rsa
Now you can add a new
remote
that uses your new ssh key# git remote add <remote_name> git@<new_host>:<username>/<repo>.git $ git remote add bitbucket git@bitbucket-deadbeef:deadbeef/some-repo.git
Now we can push to our new remote with our new ssh key!
$ git fetch bitbucket master $ git push bitbucket master
Submodules
Adding changes in the submodule
From Stack Overflow:
A submodule is its own repo/work-area, with its own
.git
directory. When cloning, use the--recurse-submodules
.
So, first commit/push your submodule's changes:
$ cd path/to/submodule
$ git add <stuff>
$ git commit -m "submodule changes"
$ git push
Then, update your main project to track the updated version of the submodule:
$ cd /main/project
$ git add path/to/submodule
$ git commit -m "updated my submodule"
$ git push
Updating all submodules
If you want to update all your submodules to the latest commit available from their remotes:
$ git submodule foreach git pull origin master
Last updated