git commands
You can install Git CLI using:
$ sudo apt install git # Debian, Ubuntu...
$ brew install git # macOS
$ git --version
Aside from git clone
, directories must have a parent with a .git
to use git commands. It's automatically created when cloning a remote Git project, but you can also use (see also: "git remote"):
$ git init # create .git
You'll have to configure GIT before you can use it. The name and the email are used to sign commits. Anyone who can access the commits knows who committed (name+email) and when.
$ git config --global user.name "Example Example"
$ git config --global user.email "example@example.com"
You may also create aliases:
$ git config --global alias.toto 'add .'
$ git toto # same as 'git add .'
โก๏ธ See ~/.gitconfig
. You can use --local
for a per-project configuration. See the configuration using: git config [...] -l
.
Basic Git commands
git clone
Download a GIT repository from a Git server.
# basic clone
$ git clone URL
# clone and store the project in "folder"
$ git clone URL folder
# clone a branch (see branching)
$ git clone URL -b name
$ git clone URL --branch name
git add
Track and stage files.
# add files/folders manually
$ git add file
$ git add file1 file2 folder
# stage all files
$ git add .
$ git add *
# stage only specific lines
$ git add -p file
git status
List information such as untracked, modified, and staged files.
$ git status
โก๏ธ See also: git diff
and git log
.
git commit
Create a commit with all the staged files. Every commit must have a message explaining what's in the commit.
# open "vim" to enter the message
$ git commit
# pass the message directly
# press SHIFT+ENTER for multi-line messages
$ git commit -m "message"
$ git commit -am "xxx" # automatically add modified files
$ git commit -m "xxx" --allow-empty # allow an empty commit
git pull
Ensure the local project is up-to-date with the latest commits, or download them and git merge
if necessary.
$ git pull # current branch
git fetch
Same as git pull
, but does not merge changes.
$ git fetch # current branch
$ git fetch origin # all branches on a remote
โก๏ธ You will have to use git merge
or git rebase
.
git push
Ensure the remote is up-to-date with the latest commits, and push them to the remote if necessary.
$ git push # current branch
Git branching
git branch
You can list, create, and delete branches.
# list all branches
$ git branch -a
# create a branch
$ git branch "branch_name"
# delete a branch
$ git branch -d "branch_name"
git checkout
Navigate to the project corresponding to the given commit.
# navigate to commit xxx
$ git checkout xxx
# navigate to branch "branch_name"
$ git checkout branch_name
# create a branch from the current commit,
# then navigate to it
$ git checkout -b "branch_name"
git bisect
If the project was working in commit A, and not working in commit B, then you can use git bisect
to find the bad commit. It uses a binary search algorithm.
$ git bisect start A B
$ git bisect bad # not this one
$ git bisect good # it works here
$ git bisect skip # skip
$ git bisect reset # exit
git cherry-pick
You can get a commit from another branch with git cherry-pick
. The commit is added to the history of your branch.
$ git cherry-pick SHA1 # pick a commit
$ git cherry-pick SHA1 --no-commit # pick only files
git stash
Before a merge, you cannot have changes locally that were not committed. You can use git stash
to put them on a shelf
and pop
them when you're done.
$ git status # some files not committed
$ git stash # save changes
$ git [...] # any command that might do a merge
$ git stash pop # load back your changes
git merge
Merge a target's history (e.g., its commits) in our history.
$ git merge xxx # a commit
$ git merge "branch_name" # a branch
If we both edited a file, it generated a conflict. โ ๏ธ Conflicts need to be handled for the merge to end.
Option 1: Use git status
to list all problems and solve them. Each file will have conflicts marked like this:
<<<<<<< HEAD
This is the content from the current branch.
=======
This is the conflicting content from branch_name.
>>>>>>> branch_name
Option 2: Abort the merge
$ git merge --abort
โก๏ธ See also: git mergetool
to use a merge tool.
Git Rebase
The command git rebase
is used to edit a repository commit history. There are many cases, such as
- ๐งผ Renaming commits
- ๐ฆ Merging multiple commits into one
- ๐ฃ Rearrange/Delete commits
- ๐ซ Delete files that were previously committed
- ...
You will usually work on a range of commits. The range starts with your current commit, and ends with the provided commit.
# Ex: rebase the last 10 commits
$ git rebase -i HEAD~10
Once inside the interactive editor (vim), you will see lines such as:
pick SHA1_HEADER commit_message
You can replace the instruction "pick" with
-
reword
: edit commit message -
edit
: edit commit -
squash
: merge this commit with the previous one -
fixup
: squash, and discard the commit message -
exec
: run a command -
drop
: remove/drop commit
Then, close the editor (on Windows: CTRL+C, then :wq
). The editor will open itself again, according to the instructions you used.
Process each commit until the rebase is done.
Additional commands ๐งช
$ git status # check where you are
$ git commit --amend # modify commit
$ git rebase --continue # next task
Git Logs
git diff
Show differences between two commits
$ git diff
$ git diff <COMMIT>
$ git diff --check <COMMIT> # markers/whitespace errors
โก๏ธ See also: git difftool
to set up a tool to view diffs.
git log
Browse your commits. Mix options to tune the output.
$ git log
$ git log -n # last n commits
$ git log --oneline # one line per commit
$ git log --decorate # ...
$ git log --stat # changed files
$ git log -p # show diff
$ git log --pretty=fuller # custom: https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-log.html#_pretty_formats
$ git log --no-walk <COMMIT> # see one commit
$ git log --graph # draw graph
$ git log --grep="feat:" # filter by message
$ git log -- README.md # filter by files
Other commands such as shortlog
and reflog
are based on log
.
gitk
GUI to browse commits.
$ gitk
git shortlog
Summary of commits per user.
$ git shortlog
git reflog
One-line per commit with the name, data, and SHA1.
$ git reflog
git ls-remote
Get information about the remote repository.
$ git ls-remote
$ git ls-remote --heads
$ git ls-remote --tags
$ git ls-remote --heads --tags
git remote
A few commands you might use when dealing with remotes.
To list remotes:
$ git remote # list remotes
local
origin
$ git remote -v # remote + URLs
origin xxx.git
To get details about a remote:
$ git remote show <remote_name> # show details
Fetch URL: xxx.git
Push URL: xxx.git
[...]
To add a remote, use:
$ git remote add origin CLONE_URL
To update a remote URL (ex: repository renamed/moved, HTTP to SSH):
# get the current URL
$ git remote get-url origin
# update the URL
$ git remote set-url origin NEW_URL
Other notes ๐
Use commits from a previous project
The goal is to "steal" commits from another local repository. For instance, if you started a project from scratch, but want to get back the previous project commits.
# remove everything as you don't want old files
$ cd AnotherRepository
$ rm -rf *
$ git add .
$ git commit -m "feat: delete everything"
# move to the other repository
$ cd ../YourRepository
$ git remote add other ../AnotherRepository
$ git fetch other
$ git merge other/main --allow-unrelated-histories
# Now, your repository has commits from the previous repository
๐ช Git extras ๐ช
๐ช Git submodules
Git submodules are the appropriate way to store (link) external Git repositories inside a Git repository.
# init submodules for a cloned project (v1)
$ git submodule init
$ git submodule update
# init submodules for a cloned project (v2)
$ git submodule update --init --recursive
# to clone a project and init submodules
$ git clone --recursive URL
$ git clone --recurse-submodules URL
# to add a Git repository as a submodule
$ git submodule add CLONE_URL
$ git submodule add CLONE_URL LOCAL_PATH
You can find your submodules in .gitmodules
.
git subtree
Git subtree is similar to git submodules, but external repositories commits are merged and part of the project history.
This can be convenient when you need to edit the code of an external repository which you can't do using submodules, but forking the external repository and using it with submodules is better.
$ git subtree add --prefix path/to/folder URL commit -squash
$ git subtree pull --prefix path/to/folder URL commit -squash
๐ช Git Large File Storage
Git LFS should be used with caution. It offers a dedicated Git storage solution for large files; however, for free users utilizing SaaS Git servers like GitHub, it does have several limitations.
For example, GitHub free users have impractical bandwidth quotas and storage constraints.
Some commands you might use:
$ git lfs init
$ git lfs update
$ git lfs ls-files
$ git lfs fetch --all origin
$ git lfs uninstall
See also: .gitattributes
.
Diff and merge tools
Git clients
- meld (๐ป)
- TortoiseGitMerge (๐ป)
Git tools
- Beyond compare (๐ป)
- diffuse (๐ป)
- tkdiff (๐ป)
- kdiff3 (๐ป)
๐ป To-do ๐ป
Stuff that I found, but never read/used yet.
-
git show
-
git tag
,git tag -a xxx -m yyy
,git push origin xxx
-
git reset
-
git restore
-
git switch
-
git filter-branch
(see disable git-lfs, and here) -
git filter-repo
-
git diff -U3 > xxx.patch
-
git apply xxx.patch
-
git format-patch -1 HEAD
-
git grep
Cheatsheets
find .git/objects/ -type f -empty | xargs rm
git fetch -p
git fsck --full