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

Git tools


๐Ÿ‘ป 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

corrupt git files

find .git/objects/ -type f -empty | xargs rm
git fetch -p
git fsck --full