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. - Git silently fetches changes/differences from the remote repo. So if you are working in a branch and diffs it against your master and it suddenly shows strange changes, then switch to master, it will likely tell you that your branch is after origin/master. Pull it and rebase.
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 init.defaultBranch main 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 Also set the strategy when pulling and applying local commits: git config --global pull.rebase true Explanation for the pull.rebase setting: "rebasing If you pull remote changes with the flag --rebase, then your local changes are reapplied on top of the remote changes. [...] merging If you pull remote changes with the flag --merge, which is also the default, then your local changes are merged with the remote changes. This results in a merge commit that points to the latest local commit and the latest remote commit. [...] best practice It is best practice to always rebase your local commits when you pull before pushing them. As nobody knows your commits yet, nobody will be confused when they are rebased but the additional commit of a merge would be unnecessarily confusing. Published commits are, however, usually merged, for example when branches are merged." Source: https://sdqweb.ipd.kit.edu/wiki/Git_pull_--rebase_vs._--merge 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" 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 core.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 service ntp start NTP status can be checked with: ntpq -p systemctl status ntp 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 -- <filename or folder> Reset file to master or other branch - revert/udo file changes git checkout origin/master <filename or folder> or for branch other than master: git checkout origin/<branch name to "revert" to> <filename or folder> 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 Revert a commit: Create a branch, if you intend to make a pull request on GitHub. git revert <commit-id> This makes a new commit that reverts the commit and opens the editor to write a commit message.
GitHub/Bitbucket - 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. For Bitbucket: Click on the user icon in the top right, then go to Settings, Personal Settings, Security, SSH Keys. Then click Add key, fill in a fitting label like Computer, paste the contents from id_rsa.pub in Key and click Add key. For Github: 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. For GitHub: git remote set-url origin git@github.com:<repository owner>/<repository>.git For Bitbucket: git remote set-url origin git@bitbucket.org:<repository owner>/<repository>.git To switch back to HTTPS do the following. For GitHub: git remote set-url origin https://github.com/<repository owner>/<repository>.git For Bitbucket: git remote set-url origin https://<your bitbucket username>@bitbucket.org/<repository owner>/<repository>.git
X11 Forwarding and GitHub
You may get "X11 forwarding failed on channel 0" when connecting to Bitbucket or GitHub after switching to passwordless authentication. To solve this, edit your local ~/.ssh/config file so it disables X11 Forwarding for GitHub: Host bitbucket.org ForwardX11 no 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
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 like this: https://<username>@github.com/<username>/<project>.git In Authentication method, select Password. In Password, fill in the token. 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.
Mirror from GitHub to GitLab
As of 2021 sadly it has become a "Premium" feature of GitLab to mirror data from another repository. A possible workaround is to add an additional origin and push to both GltHub and Gitlab: git remote set-url --add origin git@github.com:<username>/<project>.git Or: git remote add github git@github.com:<username>/<project>.git git remote add gitlab git@gitlab.com:<username>/<project>.git Check with: git remote -v Then push to one specific or all: git push github git push gitlab git push https://9to5answer.com/mirroring-from-gitlab-to-github https://stackoverflow.com/questions/11690709/can-a-project-have-multiple-origins
GitLab project description and picture
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.
Hooks
There are several hooks available, check the .git/hooks/ directory which contain samples of hooks. To create a pre-commit hook, create a file in .git/hooks/pre-commit and fill it with the commands to run. The hook is executed with the repository root directory as the path. So commands like git add can be run as if you were standing in the root directory.
Git bash auto-completion / autocompletion
If you type git br and then type Tab then Bash should spell that out to git branch. If not, ensure the Bash completion package is installed (in Debian): apt-get install bash-completion
Golden Rule of Rebasing
"The golden rule of Rebasing is that we should never use git rebase on public branches. If other people are using the same branch then they may get confused by looking at the changes in Master branch after GIT rebasing. Therefore, it is not recommended to do rebasing on a public branch that is also used by other collaborators." Source: https://www.knowledgepowerhouse.com/what-is-the-golden-rule-of-rebasing-in-git/1952
Rename master branch to main
Git: git pull git branch -m master main git push -u origin main GitLab: Go to the repository on GitLab, Settings, Repository, Branch defaults. At Default branch click Expand, change Default branch from master to main, click Save changes. At Protected branches, click Expand, in the Protected branch list remove master, add main using the form above if you like to. Then run this to remove master branch: git push origin --delete master Source: https://bud.agency/rename-master-branch-main-git-gitlab/ Then on other hosts using the repository: git branch -m master main git fetch -p origin git branch -u origin/main main git remote set-head origin main If master is left locally, remove it: git branch -D master Source: https://stackoverflow.com/questions/71951105/how-to-change-current-branch-in-git-from-master-to-main After this you may have a remotes/origin/HEAD -> origin/main branch, this is normal. "is not a branch, but a symbolic pointer (HEAD) to a branch. It references the default branch that will be checked out when you are cloning the remote repo." It can be removed: git remote set-head origin -d Source: https://stackoverflow.com/questions/12613793/why-is-there-a-remotes-origin-head-origin-master-entry-in-my-git-branch-l If you are mirroring GitLab to GitHub, you also need do to this: GitLab: Go to the repository, Settings, Repository, Mirroring repositories. There will be an error in the mirroring list at the bottom: 13:push to mirror: git push: exit status 1, stderr: "To https://github.com/<username>/<project>.git\n ! [remote rejected] master (refusing to delete the current branch: refs/heads/master)\nerror: failed to push some refs to 'https://github.com/<username>/<project>.git'\n". If not, click on the synchronization button, then reload the page after a while. The error shows that it has tried and sent main to GitHub, but failed to remove master. GitHub: Go to the repository, Settings, Branches, Default branch, click the arrows button, select main, click Update, click that you understand. Go to the repository main page - click on the repository name, <n> branches, search for master, click the recycle bin button, click the X at the search to check that main is left. GitLab: Go to Go to the repository, Settings, Repository, Mirroring repositories again and click the synchronization button, reload the page after a while. The error should be cleared.
Make a normal Git repository a bare (shareable/remote) repository
A normal repository cannot accept pushed changes. For that you need a bare repository, but does not have a so-called working tree which is the list of files. It only has the .git directory renamed to repository.git. That is why GitHub for example has URL:s like github.com/<owner>/<repository.git>. The following will preserve the normal repository while creating a bare repository in the same directory and making git ignoring it in the normal repository. Both have the cake and eat it. 1. Start with a regular repository made with git init, for example: mkdir repo cd repo git init echo hello > file.txt git add . git commit -m 'Create repository.' You now have a regular git repository with 1 commit. The files in the directory except the .git directory are the "working tree". 2. Add the not yet created repo.git directory to .gitignore and commit the changes: echo "repo.git" >> .gitignore git add . git commit -m 'Update .gitignore.' 3. Copy .git to the new "bare" repository directory repo.git: cp -R .git repo.git 4. Configure the copied repository directory to be bare: git --git-dir=repo.git config core.bare true Not doing this results in "remote: error: refusing to update checked out branch: refs/heads/main" when trying to push commits. 5. Set the normal/local directory origin to the bare repository in the same directory using a file path as the origin URL: git remote add origin ./repo.git git fetch origin git branch --set-upstream-to=origin/main main The directory structure now looks like this: file.txt .git .gitignore repo.git You now have 2 repositories in this directory, the normal one with file.txt, .git and .gitignore and the bare one with repo.git. 6. Make a new commit in your normal repository and push it: echo "hello again" >> file.txt git add . git commit -m 'Commit from original repository.' git push 7. Get out of the repository and make a clone: cd .. mkdir clone cd clone git clone ../repo/repo.git cd repo git pull 8. Make a commit from the clone and push it: echo "and hello again" >> file.txt git add . git commit -m 'Commit from clone.' git push 9. Check that it is in the original repository: cd .. cd repo git pull git log If you want to clone your repository on another host you can do this: git clone user@hostname:/path/to/repo/repo.git Reference: https://stackoverflow.com/questions/2199897/how-to-convert-a-normal-git-repository-to-a-bare-one
This is a personal note. Last updated: 2024-04-07 17:59:43.