git cheat sheet / GitLab cheat sheet / GitHub cheat sheet

A little cheat sheet for using git


What do you need to know that confused me? Well here is a short list

- Git stores all information repos in local directory called .git in the project root directory. So you can have a complete repo on a floppy disk if you like and it fits.

- Very important to understand: If you are on one branch and makes changes to the files and then forgetting to  commit the changes to the branch, then these changes will continue to exist even AFTER switching branch. For the uninformed, it looks like the branching is broken - you switched branch and the changes you wanted to throw aside into a branch is still there. But you need to COMMIT the changes to the working branch (or stash them) BEFORE switching to another branch. Then it works.

- Git mostly talks to the outer world through clone, push and pull. Aside from that
you are working locally.

- A good way to learn how git works is to install it with apt-get install git, make a test directory, make a text file, init a new repo and add the text file and make branches and play around. Pretty fast you learn the basics. Just remember the thing noted about forgetting to commit before switching to another branch, or you'll get confused.

- Git uses vi editor when it detects merge changes that it cannot handle on it's own. You are encouraged to learn vi (it pays off) or edit git configuration to switch default editor.

- It matters what branch you stand in when making a new branch. If you make a new branch B standing in branch A, then B WILL be based on branch A. This is a HUGE pitfall if you are not aware of it. If you don't want this effect, make sure you switch to master BEFORE creating a new branch, or you will get the changes from the current branch merged into master when merging the new branch.


A list of git commands

<Texts> show where to put in info.

Setup - do this first
	sudo apt-get install git

Configuration, do also this first to setup your user and activate coloring
	git config --global user.name "firstname lastname"
	git config --global user.email "valid@email.address"
	git config --global color.ui auto	
	git config --global core.editor vim	
	git config --global push.default simple

Configuration for local repos, if you want to go under another e-mail for specific projects, standing in the repo root dir:
	git config user.email "different.valid@email.address"

Also set sometimes this to avoid merges:
	git config pull.rebase true

List current configuration, note that if you are standing in a repo with different settings, then those are displayed last, overriding the ones above:
	git config --list

NOTE: It is advisable to also set some of these running as root if you sometimes are logged in as root. Like global user.name, user.email, color.ui and color.editor. Check with the list command above and compare the output for your user with root so they are identic, or as you want to have it.

Also make sure your local time is correct by installing ntp to avoid wrong commit dates:
	sudo apt-get install ntp
	sudo ntpq -p

Clone a repo - to download a repo from somewhere, be ready with username and password
This creates a subdirectory with the project name.
	git clone https://github.com/<username>/<projectname>.git

Reset current situation to original before files was edited
	git reset --hard HEAD

Fetch latest changes from remote repo
	git pull 

Create a new local repo (makes .git directory)
	git init 
	
Remove the local repo (simply remove the .git directory, that's all)
	rm -rf .git/

Add files / stage files before doing a commit:
	git add ./ OR git .
	
Store the current changes as a commit
	(git add <changed files according to git status>)
	git commit -m "<Write what has been changed here>"

Create a new (local?) branch
	git checkout master (VERY important, new branch will be based on current branch)
	git checkout -b <branch name>
	OR
	git branch <branch name>
	git checkout <branch name>

	To save changes in a branch, do a regular commit, like
	git add <changed files according to git status>
	git commit -m "<Write what has been changed here"

	NOTE! it is VERY important to add files before committing, this "stages"
	changed files. If you don't do this and switch branch, you will
	find that the changes in the branch are still there even after
	switching branch. This is confusing.

Switch to another branch, replace <branch name> with master to go to master
	git checkout <branch name>

Rename local branch
	git branch -m <oldname> <newname>

List available remote branches:
	git branch -v -a

Fetch a remote branch and prepare it locally(?):
	git branch <branch name> remotes/origin/<branch name>

NOTE about name:

	<branch name> MUST reflect the remote branch name after remotes/origin, it may also contain slashes.
	Otherwise git will complain because the remote and local branch names differ.

	git checkout <branch name>
	git pull

Rename a branch
	git branch -m <oldname> <newname>

Push a remote branch to remote
	git push <remote-name> <local-branch-name>:<remote-branch-name>
	<remote-name> = origin (most often)
	Next time you do git push, you will be prompted to:
	git push --set-upstream origin <remote? branch name>

Work with someone elses (remote) branches on GitHub - 2017 edition
For some reason you suddenly don't need to mess around with origins and stuff.
You can work with remote branches like they were local.

	git clone <.git link>
	git checkout <branch name>
	git add <files>
	git commit -m "<reason text>"
	git push

Note that this seems to create a local copy of the branch you're checking out.
Also note that you need to be collaborator (participant?) on the branch.

Remove/delete/untrack a file, this will not delete the file from the file system, just from Git
	git rm filnamn
	git commit -a -m "<Write why file was removed>"
	
Remove local branch
	git branch -d <branch name>
	
Merge branches, first switch to the branch you want to keep, then request a merge
	git checkout <branch name to keep>
	git merge <branch name to merge into the one to keep>
	git branch -d <branch name to merge>

Merge branch into master:
	(git rebase on branch... git pull etc. is good before)
	git checkout master
	git merge <branch to merge>
	git push

Rebase, merge, push and delete:
	git checkout master
	git pull
	git checkout <branchname>
	git rebase master
	git checkout master
	git merge <branchname>
	git push
	git branch -d <branchname>
	git push origin --delete <remote-branchname>

	Note: do NOT forget to pull on master first, otherwise you will miss latest updates.

Update a branch to master:
	git checkout <branchname>
	git rebase master <branchname> 
	(<branchname> is not necessary)

Resolving a conflict during a rebase:
	git checkout <branch>
	git rebase
	<conflict appears>

	Edit the files, find HEAD text, take the correct part, delete the rest

	git add <edited files>
	(git commit -m "What has been changed..." - maybe not needed)
	git rebase --continue
	git push --force

Check current uncommitted difference/changes
	git diff

Check total diff for branch to master, standing in the actual branch
	git diff HEAD master

Check current uncommitted but staged (added) changes:
	git diff --cached

Check unsaved changes, files that have not been added and so on
	git status

Check commit log
	git log

Show specific commit and the data committed
	git show <commit hash>

Reset file - revert/undo file changes
	git checkout -- <file name>
	
Check configured remote repos/servers
	git remote 
	OR for mer info
	git remove -v
	
	"origin" is the default name for the remote server

Ignore files
	Local folder only, not affecting repo .gitignore: add to .git/info/exclude
	Following the repo: add to .gitignore

Ignore tracked files locally
	git update-index --assume-unchanged <file name>

Un-ignore tracked files locally
	git update-index --no-assume-unchanged <file name>

List ignore tracked files locally
	git ls-files -v | grep -e "^[hsmrck]"

Ignore tracked files locally, alternative, causes conflicts when changes are upstream:
	git update-index --skip-worktree <file name>

Un-ignore tracked files locally, alternative:
	git update-index --no-skip-worktree <file_name>

List ignore tracked files locally, alternative:
	git ls-files -v|grep '^S'

View change history for one file
	git log -p <filename>

Combine (squash) last X commits:

git log (to check the commits, count the ones you want to combine, then put that number where the X is below.)
git reset --soft HEAD~X
git commit

Edit other commit messages than the last one (that can be done with git commit --amend), 
	git log
	Count the commits down to and including the one to edit and put in X:
	git rebase -i HEAD~X
	In the editor, replace pick with reword on the line to edit, save the file.
	A new editor will come up, edit the commit.

	Source: https://stackoverflow.com/questions/179123/how-to-modify-existing-unpushed-commit-messages

Put in changes before commit X:

	Make a backup of the repository
	Find the commit to reverse to, if initial, go down to the first, copy the id:
	git log
	Create a new branch from master using the commit:
	git checkout --orphan new-master <id-of-the-commit>
	If you want to start clean, remove all files:
	git rm -rf .
	Check if there are leftovers and remove them with rm -rf as usual files.
	
	You are now ready to move your changes into the directories, do so.
	Then to commit, do as usual with the addition of a date:
	git commit --date="<YYYY-MM-DD H:i:s>" --message="<message>
	
	Now lets rebase master on top of this branch, be prepared for conflicts:
	git rebase --onto new-master --root master

	Solve any eventual conflicts.

	To check that the rebased master is the same state as it was before the rebase, do this:
		git diff master@{1}
	Or this:
		git diff orig_head
	No output should be returned.

	Source: https://stackoverflow.com/questions/16762160/add-commits-before-root-commit-in-git


GitHub - authenticate Linux login using SSH keys without username and password

Go to your local ssh directory:
cd ~/.ssh/

Check for ssh key:
ls -la|grep id_rsa.pub

If it ain't there, generate it:
ssh-keygen -t rsa -C "local-username@hostname"

NOTE, enter the login you use to login to the host and hostname of computer in the e-mail, it it's not necessary to enter your own email here as this key is attached to the current host you are on. So if you login with user and the hostname is host, enter user@host.

To get username:
echo $USER

To get hostname:
echo $HOSTNAME (or cat /etc/hostname)

You have now generated 2 files, id_rsa and id_rsa.pub. Never share id_rsa, it's your private key.
But output contents of id_rsa.pub:

cat id_rsa.pub

Copy the contents, go to https://github.com/settings/keys (or your image in the top right, then Settings in the menu, then Keys in the left panel) and login with your GitHub password.

Click New SSH Key and paste the contents from id_rsa.pub and save it.

Go to your project root location (the folder with the .git folder in it) and do:
git remote -v

Make sure it does NOT use https, this is not working for example:
origin    https://.../.git (fetch)
origin    https://.../.git (push)

If it does, then you need to change origin so it doesn't use HTTPS:
git remote set-url origin git@github.com:<your-git-account>/<your-git-project>.git

To switch back to HTTPS:
git remote set-url origin https://github.com/<your-git-account>/<your-git-project>.git


X11 Forwarding and GitHub

You may get "X11 forwarding failed on channel 0" when connecting to GitHub after switching to passwordless authentication.

To solve this, edit your local ~/.ssh/config file so it disables X11 Forwarding for GitHub:

Host github.com
	ForwardX11 no

Host *
	ForwardX11 yes

Reference: https://unix.stackexchange.com/questions/240013/x11-forwarding-request-failed-when-connecting-to-github-com


Publish existing repository to GitLab


Create the project on GitLab - click on the plus sign (+) in the top bar, then go New project. Fill in the name and the description.

Copy the HTTPS address to the console, like if you should pull it.

In the terminal, do:
git remote add origin https://gitlab.com/<username>/<project>.git

Do a first push:
git push --set-upstream origin master

Set it to track, otherwise it will not work:
git branch --set-upstream-to=origin/master master

Go back to GitLab and in the project go Settings, Repository, Protected Branches, under Protected branch, click Unprotect on master.

In the terminal, push up new changes if any:
git push


Mirror from GitLab to GitHub, GitLab project description and picture

Additional things you may want to do is to mirror the project from GitLab to GitHub, set project description and title.

To mirror you need to grant GitLab access to GitHub using a key.

In GitHub, click on the user profile picture in the top right, go to Settings, Developer settings, Personal access token.

Click Generate new token. Name it GitLab or something and check repo and delete_repo.
You now get a token that works as a limited password for GitHub.

Create a new empty project in GitHub with the same name as on GitLab.

Copy the full address to the project and go to GitLab and the project.

Go to project settings, Repository and Push to a remote repository.
Fill in the GitHub address and prepend it with username and the token, like this:
https://<username>:<token>@github.com/<username>/<project>.git

Save it. To test, click the Repository Settings page subtitle and go to Push to a remote repository again and click the new hidden Update now button.

To set an image for the project, go to project settings, General project settings and fill in the description, in the Avatar file field select the image and upload it.


Rebase navigation when solving conflicts


To find out how many commits that are left to rebase and maybe solve conflicts on, use git log <current branch name> and find the commit that failed - this one is noted both in the conflict details and in the end of the sections in the files that need to be changed. Then count the commits above it, note that not all may fail.

Regarding the syntax of these sections:

<<<<< HEAD
The data here is the current data.
======
The data here is the incoming data that failed to merge.
>>>>> Name of the incoming commit

Sometimes it may look like this - without any current data selected:

<<<<< HEAD
=====
Incoming data.
>>>>> Name of the incoming commit

This seems to mean that it failed to find the matching insertion start point in the current data. Check the incoming data, then go upwards and try to find where HEAD may fit, somewhere that the incoming data can be used as a replacement.

To solve a conflict, remove all the sections and only leave what should be left in the file. Then add the file with git add. When all are added, do git rebase --continue. If it says there are nothing to be done, do git rebase --skip. To abort, do git rebase --abort.

This is a personal note. Last updated: 2019-06-26 11:22:44.



LinkedIn
Klebe.se

Don't forget to pay my friend a visit too. Joakim