Illustration by Muhammad Ribkhan
An extensive collection of meticulously curated Git questions and answers. Concepts like branching, merging, and committing to advanced topics such as rebasing, cherry-picking, and submodules, we've got you covered.
Pull requests are welcome.
- Setting Up
- Basics
- Branch & Merge
- Workflow
- Collaboration & Remote Repositories
- Advanced Topics
- Best Practices
- Tools & Extensions
- Tips & Troubleshooting
- Continuous Integration & Deployment
- Security & Access Control
To make copy and pasting easier, set the environment variable GQ_URL
and friends to their respective
values.
Example:
export GQ_URL=https://github.com/jcormir/git-questions.git
export GQ_BRANCH=awesome-branch
export GQ_TAG=v1.0
export GQ_COMMIT=c8e491e
export GQ_REPO=git-questions
export GQ_FILE=file.txt
export GQ_DIR=a_directory/
Setup new repostories, clone existing ones, and just getting to know Git.
Create an empty Git repository or reinitialize an existing one.
git init $GQ_REPO
Running git init
in an existing repository is safe. It will not overwrite things that
are already there.
To clone an already existing repository.
git clone $GQ_URL
The repository file .gitignore
is a configuration file used in Git repositories to specify
files and directories that should be excluded from version control.
Example that excludes C objects (.o), Python compiled bytecode (.pyc), and directory named build
.
*.pyc
*.o
build/
Head to gitignore.io to get .gitignore
entries for your project.
Whether you're working by yourself or on a team, you should have a repository work flow that involves merging branches. Feature branches, long term release branches, etc.
New local branch based on HEAD
.
git branch $GQ_BRANCH
Switch repository branch.
git switch $GQ_BRANCH
Shortcut to create and switch to a branch in a single command.
git switch -c $GQ_BRANCH
New local branch from existing branch.
git branch $GQ_BRANCH <base-branch>
If you want to start your new local branch based on a specific commit or tag, then you can provide the commit hash or tag name as the starting point.
git branch $GQ_BRANCH $GQ_COMMIT
After working on your new local branch for some time, you might want to publish it in your remote repository, to share it with your team:
git push -u origin $GQ_BRANCH
The -u
or --set-upstream
tells Git to establish a tracking reference, which argument-less
git-pull and other commands make use.
To get a list of branches that have been merged into the current branch.
git branch --merged $GQ_COMMIT
To get a list of branches that have not been merged use --no-merged
.
To merge changes from another branch into the current branch.
git merge $GQ_BRANCH
If you would like to keep the repository history clean of the commits from the merging
branch, you can use the --squash
argument to squash the commits to a single commit and
stage. Allowing for commit message and merge conflict changes.
git merge --squash $GQ_BRANCH
When done push the changes to the remote.
Annotated tags are stored as objects in the repository. They’re checksummed; contain the tagger name, email, and date; have a message; and can be signed and verified.
It’s recommended to create annotated tags to have this information; but if you want a temporary tag, lightweight tags are available too.
git tag -a v1.0 -m "Version 1.0"
Search for tags that match a particular pattern. If you’re interested only in looking at the 1.0 release tags, run this:
$ git tag -l "v1.*"
Commands you will use throughout the development day.
To track a file or add changes that are yet apart of a commit.
git add $GQ_FILE
If you need to remove a file from the staging area without removing to local file, maybe
you git add
a file by accident and need to remove it.
git reset HEAD -- $GQ_FILE
If you need to remove a directory from the staging area.
git reset HEAD -- $GQ_DIR
Your changes will be kept. When you run git status
the file will once again show up as
modified but not yet staged.
If you're looking for the revision and author that last modified each line of a
file, the git blame
command does exactly that.
git blame
If you would like to limit the output to a line range use the -L
argument.
git blame -L 26,28
Other useful options to the git blame
command. To ignore whitespace include -w
, which
a lot of web UI don't do by default. To detect lines moved or copied in the same commit
include -C
, or in the commit that created the file and another -C
, or in any commit
at all include another -C
.
git blame -w -CCC
To view the changes that are yet to be staged, use the git diff
command with no switches.
git diff
If you already staged your changes, you can view those changes by adding --cached
switch.
git diff --cached
If you want to diff on words vs lines you can by adding --word-diff
switch.
git diff --word-diff
To pick through the repository commit history use git log
.
List commits that are reachable by following the parent from the given commit(s), but
exclude commits that are reachable from the one(s) with a prefix of ^
.
git log
The output is given in reverse chronological order.
commit 0113f8d73745c3cda3a32360772f6055828012d3 (HEAD -> main, origin/main, origin/HEAD)
Author: Jonathan Cormier <jonathan@example.net>
Date: Sun Sep 3 22:05:35 2023 -0300
If you want basic one line commit descriptions you can use --oneline
argument.
To narrow the output a special notation <commit1>..<commit2>
can be used as a short-hand
for ^<commit1> <commit2>
. For example, either of the following may be used interchangeably:
git log origin..HEAD
git log HEAD ^origin
HEAD
is a reference to the latest commit in the repository.
If you would like to search through the repository log, you can use git log -S
and
suppy it a regular expression for filtering.
git log -S $GQ_REGEXP
If you want to see the revisions include the -p
switch.
Once you have your changes staged for commit using git add
. You need to commit.
git commit -m "Message"
You can make multiple commits before you push them to a remote, if the situation calls for it. If you have too many commits you can squash them to keep the repository history clean.
To see what changes are staged for commit, untracked files, etc. Git status
is where you
will find that information.
git status -s
Use the -s
argument for short output with just change type (M, ??) and filename.
If you would like to stash the current working directory and index changes to work on later or
commit at a later time. Use the git stash
command to bring the repository back to HEAD
.
git stash
This can be done multiple times, if you want to make changes and stash those you can. List the current stashes.
git stash list
Include the switch --all
to include untracked files.
Restore top stash by applying it to the current working directory and then removing it.
git stash pop
Pull changes and merge remote repository or local branch.
git pull
Fetch changes from remote repository but don't merge them.
git fetch
To have your changes available through remotes, push them.
git push
To list the set of repositories and their location.
git remote -v
Change the URL of a remote repository.
git remote set-url origin $GQ_NEW_URL
Rebasing, cherry-picking, and managing submodules.
Clone a repository and submodules. 2.13+
git clone --recurse-submodules $GQ_URL
Performance optimization that is available in 2.8 to set the number of submodules to fetch at
the same time use -j
or --jobs
. Defaults to the submodule.fetchJobs
option.
git clone --recurse-submodules -j8 $GQ_URL
Files that are not in the index and outside .gitignore rules.
git ls-files -o --exclude-standard
To display the current git configuration with scope details.
git config -l --show-scope | cat
To remove all untracked files in a repository, you can use the following command:
git clean -fd
- Commit messages should being with a short description of 50 character limit on the first line. Followed by a single blank line with each following line a description of the changes in the commit.
- Always pull before a push to make sure you will not face any rejections from Git.
- Always pull from related branches before you start new work on your code. It will keep your branch up-to-date and reduce the chances of conflicts.
Change conflict style to zealous diff3, zdiff3
.
merge.conflictStyle = zdiff3
To make multiple step dependent tasks easier, turn them into aliases or scripts called by and alias. For example, the script update-repos.sh can be used to perform a pull on multiple directores. Make an alias for convenience.
alias.update-repos = '!update-repos.sh'
$ git update-repos
Pull for ./git-questions...
Shallow clones aren't recommended for developers.
Perform a shallow clone when the repository history isn't a requirement and the clone with be discarded.
git clone --depth=1 $GQ_URL
Perform the same shallow only on a specific branch.
git clone --depth=1 --single-branch --branch=$GQ_BRANCH $GQ_URL