- Clone a repo!
git clone [email protected]/path/to/repo.git
> for SSH checkout (recommended for extended use)git clone https://somedomain.com/path/to/repo.git
> for HTTPS checkout (easier for experimenting)- If you are cloning from GitHub, you can also use the GitHub CLI
gh repo clone path/to/repo
- Check this section for more info on SSH vs HTTPS
- Make sure your local copy of the selected branch is updated.
- Without overwriting anything, but update the status on all branches.
git fetch
- If you already fetched or you are ready to overwrite your local copy (your active branch only!), then pull
git pull
- This is actually the same as doing
git fetch
on your branch and thengit merge
, which we will see later.
- Without overwriting anything, but update the status on all branches.
- Check your repo branches
- Local branches
git branch
- All branches on remote repo
git branch -r
- Both local and remote branches
git branch -a
- You can also add
-v
to make the commands explicitly verbose
- Local branches
- Create a branch and access it
- Normal way
git branch new_branch
- (2 ways)
git switch new_branch
> Recommended option (avoidcheckout
unless necessary)git checkout new_branch
> For git versions older than 2.23
- Shortcut (2 ways)
git switch -c new_branch
> Recommended option (avoidcheckout
unless necessary)git checkout -b new_branch
> For git versions older than 2.23
- Normal way
- Get some work done lol
- Check the status of your work
git status
- Did you mess up editing a file and want to restore it to how it was beforehand? (2 ways)
git restore changed_file.txt
> Recommended optiongit checkout -- changed_file.txt
> For git versions older than 2.23
- Add changes to staging in order to prepare your commit
- Add a single file
git add new_file.txt
- Add all changed files
git add .
- Add just a hunk (small piece) within a file but not the whole file
git add -p new_file.txt
- This will open an interactive prompt for each hunk within the file. You will have to confirm an action for each hunk; input
?
to see the help for the available options. - You can do this for all files at once with
git add -p .
- Add a single file
- Did you screw up? Reset the staging
git reset
- If you are running git 2.23 or newer, you can also run
git restore --staged .
but it's longer. - You can also run
git restore --staged filename.txt
for unstaging a specific file.
- Once you've staged what you want to commit, commit.
git commit -m "This is a commit message"
- Check the commit history of the branch you're in.
git log
- If you wanna see some cool things with log, you can use something like this:
git log --graph --oneline --all
- Make sure you upload your commits to the remote repo! If your local branch is brand new, you must add it to the remote repo.
- New branch
git push -u origin new_branch
- Previously existing branch
git push
- All your modified local branches
git push origin --all
- New branch
- Move to another branch
git switch another_branch
- Merge some branch into your current branch (assuming default behavior of pull is merge)
git merge branch_that_will_be_merged_into_current_branch
- Remember that pull = fetch + merge, so you can also do
git pull branch_that_will_be_merged_into_current_branch
For more info check the GitHub Git Cheat Sheet
checkout
can be used to switch branches and/or restore working tree files, which means that you can do things like undo/restore commmits and overwrite local changes, or detach the HEAD (navigating a commit which is not the latest on its branch).
switch
is only used for switching and creating branches. It cannot discard changes to tracked files: if you've changed a tracked file and want to switch branches, you'll need to stash or commit the changes.
switch
as well as restore
were both added in git 2.23 and they are actually functionality subsets of checkout
. They were added for clarity because checkout
can do so many things that using it easily becomes confusing and possibly dangerous.
In the advanced section you can see a specific use case of checkout
that cannot be handled with these 2 new commands.
The following are some best practices that may be useful, taken from this blog post, as well as this tip.
This workflow is useful for updating a feature branch and merging it with the main branch. You may also use it for merging custom branches among them, but we will assume that the intent here is to merge with main. We will also assume that the feature branch is set upstream in the remote repo and you can push and pull from it; if your feature branch is local only then you can skip step 1.
- While working on a branch, if you need to pull commits from the remote repo to your local repo, use rebase instead of merge to reduce the amount of commits
git pull --rebase
- If you want to make rebasing the default behavior when doing
git pull
, do so withgit config --global --bool pull.rebase true
.- This is useful when collaborating with people on the same branch and you have to pull from the same branch more times than you need to merge branches.
- Before pushing your changes to the remote repo, perform basic housekeeping (squash related commits together, rewording messages, etc)
git rebase -i @{u}
- Make sure that you've fetched all changes from the remote repo
git fetch
- Optionally, you may also want to switch to the main branch and
git pull
from it.
- From your feature branch, simulate a merge to see any possible conflicts:
- Do a merge with the
--no-commit
flag.get merge --no-commit --no-ff main
- Examine the staged changes
git diff --cached
- Undo the merge
git merge --abort
- Do a merge with the
- Merge (do not rebase) changes from the main branch into your branch, in order to update your branch with the latest features and solve any compatibility issues and/or conflicts
- If you already pulled main, then
git merge main
- If you haven't pulled main or you're not sure, then
git pull --merge main
- If you already pulled main, then
- Switch to the main branch with
git switch main
- Enforce merge commit when merging your feature branch into main, even if a merge commit isn't necessary (check the next point for an exception), in order to make it easier to see the where and when of changes.
git merge --no-ff feature_branch
- Exception to point 4: merging a single commit (typical for stuff such as bugfixes):
git cherry-pick feature_branch_with_a_single_commit
- Push the changes to the remote repo.
- If you want to push the feature branch to the remote repo, make sure that you've set it up upstream before with
git push -u origin feature_branch
- Push the branch(es)
- Push main only with
git push
orgit push main
- Push explicitly both main and feature_branch with
git push origin main feature_branch
- Push all your local branches with
git push --all
- Push main only with
- If you want to push the feature branch to the remote repo, make sure that you've set it up upstream before with
- If you don't need it anymore, you may delete the feature branch (after merging, you won't lose the commits even if you delete the branch):
- Delete the feature branch locally
git branch -d feature_branch
- Delete the feature branch on the remote repo
git push origin :feature_branch
- Delete the feature branch locally
- Need to switch to another branch but you're not ready to commit? Stash the changes!
git stash
- You can also use
git stash save
- Untracked files will NOT be stashed! If you want to stash them as well, use
git stash -u
- Finished with the other branch and want to recover your stashed away work? Then pop it!
git stash pop
- This will apply the stashed work into your current branch and delete the stash.
- If you don't want to delete the stash (useful for applying the changes to multiple branches), then do
git stash apply
- If you stash multiple times without popping, the stashes will accumulate! Manage your stashes!
- List your stashes with
git stash list
- Apply a particular stash with
git stash apply stash@{X}
, withX
being whatever stash ID you want. - Delete a particular stash with
git stash drop stash@{X}
- Delete all the stashes with
git stash clear
- List your stashes with
- Do you want to check how your code was in a specific point of time? If you have the commit id/hash, you can use checkout
git checkout commit_id
- You are now in a detached HEAD state (you are no longer attached to a specific branch). If you try to create new commits from this point, the commit will be orphaned because it will not belong to any branch!
- However, you CAN create a new branch from this state!
git branch -b new_branch_from_old_commit
- You are now attached to the latest commit of a new branch! You can now work normally and add new commits to this branch.
- From a detached HEAD state, you can go back to usual with a simple switch:
git switch branch_you_want_to_go_back_to
- If you somehow end up with orphaned commits, you will have to use git reflog to rewrite history by finding the lost commit and cherry-picking it to an existing branch. Keep in mind that orphaned commits are deleted from the local repo after 30 days.
- Sorry, no detailed instructions, find out on your own how to reflog.
DO NOT DO THIS IF YOUR COMMITS HAVE ALREADY BEEN PUSHED TO THE REMOTE REPO!
- If you regret commiting and you have not yet pushed, you can reset it!
git reset HEAD^
> If you want to undo the commit but keep the changes in your files.git reset --hard HEAD^
> If you want the nuclear option and get rid of both the commit and its changes
- If you really regret your work in your last few commits, count how many must be purged and substract them from the HEAD
git reset HEAD~4
> This means "get rid of the last 4 commits but don't get rif of the changes in the files"git reset --hard HEAD~4
> This means "burn it all and get rid of the last 4 commits forever"
- If you have a particular commit you want to reset to, use its id/hash:
git reset commit_id
git reset --hard commit_id
- Tag your current commit (useful for checkpoints such as point releases!)
- Annotated:
git tag -a your_tag -m "This is a message, like in a commit"
- Lightweight:
git tag your_tag
- Annotated:
- Display your tags
git tag
- Get info on a specific tag
git show your_tag
- Tags are not pushed when you push your branch! Push your tag!
git push origin your_tag
git push --tags
if you want to push all your tags at once.
- Do you have a special commit like a bugfix or a small update in another branch and want to apply it to your current branch? Cherry-pick it!
git cherry-pick commit_hash_goes_here
> applies the commit identified by its hash to your active branch.- Cherry-picking creates a new commit! It contains the same info as the commit you clone/cherry-pick, but it's a different hash.
- Do you want to cherry-pick a hunk inside a commit? You can! Follow these steps in order:
git cherry-pick -n commit_hash_goes_here
> Using-n
(--no-commit
) stages the changes for the cherry-pick but doesn't commit them.git reset
> Unstage the changes from the cherry-picked commitgit add -p
> Interactive patching; add the hunks you wantgit commit
> Yay!
If possible, try to use SSH. Read below for additional info.
SSH is convenient because you can set up passwordless access to repos and is secure, but set up can be a little tedious.
For setting up SSH, follow the instructions in this gist.
Once you've created SSH keys and optionally set up your work environment to work with multiple accounts, you can simply clone a repo with git clone ssh://url.com/repo.git
.
Sometimes you cannot clone a repo with SSH for a number of reasons: maybe the SSH ports are blocked inside your work network, or perhaps your repo provider does not support SSH. In that case, you will most likely use HTTPS for accessing your repos.
However, HTTPS does not use public keys and relies on username and password for accesss. Setup is significantly easier for most users but any operation on the remote repo will prompt the user and password, which is extremely annoying.
By default Git does not store usernames and passwords, but it is possible to set this up with Git's credential helpers for credential storage. However, the file is stored in plain text, which is very bad.
An alternative is using Git Credential Manager. It already comes pre-installed with Git for Windows, but can also be installed separately on MacOS and Linux. Follow the instructions for installation and usage on its GitHub page.
Note that if you're using WSL, there are special instructions for making the Windows manager available to your linux distro. Check the Windows install instructions.
- Make sure you install Git for Windows with the Git Credential Manager
- Add the Credential Manager as the credential helper in your global git config. In a WSL terminal, type:
git config --global credential.helper "/mnt/c/Program\ Files/Git/mingw64/bin/git-credential-manager.exe"
- Make sure that the path is correct for your install path.
- (Optional) If you use Azure DevOps, in a WSL terminal, type:
git config --global credential.https://dev.azure.com.useHttpPath true
- Use git normally. On first clone/pull/push, you will be asked your credentials. Afterwards, you shouldn't have to type them in anymore.
- If you change your password in your remote server, authentication will fail. You need to reject the current credentials and refresh them:
- In the WSL terminal:
git credential reject
- The terminal will display a blank line. Type in the following:
url=https://url/of/your/repo.git
- Press the Enter key to create a new blank line, and press the Enter key again on the blank line.
- Try to clone/pull/push again. You will be asked the credentials once again.
- In the WSL terminal:
- Git Credential Manager will try to automatically detect the Git provider but it may not always be successful, especially with on-premises solutions. In order to manually set up the provider, do this from a PowerShell terminal:
git config --global credential.<your_git_repo_host_url>.provider <git_provider>
- You can see the list of providers in this url
- Doing this from a WSL shell will not work, because Git Credential Manager is a Windows executable and it will look for the global .gitconfig in Windows. Make sure you run the command above from a PowerShell terminal.
These notes were created when experimenting and have not been thoroughly tested nor properly expanded upon. Proceed at your own risk.
- Make sure you've got a local commit. You may initialize a local repo with
git init
on any project folder and making sure that it has at least one commit, or you may use an already existing local repo. - On a separate folder, run:
git clone --bare path/to/local/project project.git
- This will create a folder with name
project.git
on the folder you're running the command. - Remote repo folders use the
.git
extension as a standard. - This folder is a bare repository. It does not contain a working folder, only the git files.
- This will create a folder with name
- Move the
project.git
folder to the final destination. Ideally, a shared folder such as a networked drive that everyone has access to "locally".- You may combine steps 2 and 3 by creating the bare repo directly on the final folder.
- You should now be able to clone the repo:
git clone path/to/remote/repo/project.git
- The original repo that we bare-cloned does not have an origin repo to push to. If you want to keep using it, set up a remote like this:
git remote add origin path/to/remote/repo/project.git
- On remote folder:
mkdir my_repo cd my_repo git init --bare
- On local folder:
cd my_repo git init git remote add origin ssh://myserver/my_repo git add . git commit -m "Initial commit" git push -u origin master