Skip to content

An extensive collection of meticulously curated Git questions and answers

License

Notifications You must be signed in to change notification settings

rancorm/git-questions

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Git Questions

Cover Image

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.

Contribute

Pull requests are welcome.

Table of Contents

Setting Up

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/

Basics

Setup new repostories, clone existing ones, and just getting to know Git.

Create a new repository

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.

Clone existing repository

To clone an already existing repository.

git clone $GQ_URL

Ignore files

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.

Branch & Merge

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.

Make a branch

New local branch based on HEAD.

git branch $GQ_BRANCH

Switch repository 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

Branch from an existing branch

New local branch from existing branch.

git branch $GQ_BRANCH <base-branch>

Branch from a specific commit or tag

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

Push local branch to remote repository

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.

What branches have or have not merged

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.

Merge branch

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.

Tags

Add annotated tag

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"

List tags

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.*"

Workflow

Commands you will use throughout the development day.

Stage file or changes for commit

To track a file or add changes that are yet apart of a commit.

git add $GQ_FILE

Unstage a file or directory

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.

What revision last modified a line of a file

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

Show me the differences

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

Looking through repository history

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.

Searching through repository history

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.

Commit changes

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.

Show the working status

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.

Stash working directory and index changes

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.

Restoring stash changes

Restore top stash by applying it to the current working directory and then removing it.

git stash pop

Collaboration & Remote Repositories

Pull changes

Pull changes and merge remote repository or local branch.

git pull

Fetch changes

Fetch changes from remote repository but don't merge them.

git fetch

Update a remote repository

To have your changes available through remotes, push them.

git push

List remote repositories

To list the set of repositories and their location.

git remote -v

Change remote location

Change the URL of a remote repository.

git remote set-url origin $GQ_NEW_URL

Advanced Topics

Rebasing, cherry-picking, and managing submodules.

Clone repository recursively

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

List of untracked files in working tree

Files that are not in the index and outside .gitignore rules.

 git ls-files -o --exclude-standard

Show current configuration with scope

To display the current git configuration with scope details.

git config -l --show-scope | cat

Remove untracked files

To remove all untracked files in a repository, you can use the following command:

git clean -fd

Best Practices

  • 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.

Tools & Extensions

Tips & Troubleshooting

Change conflict style

Change conflict style to zealous diff3, zdiff3.

merge.conflictStyle = zdiff3

Make and use aliases

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...

Continuous Integration & Deployment

Shallow clones aren't recommended for developers.

Shallow clone

Perform a shallow clone when the repository history isn't a requirement and the clone with be discarded.

git clone --depth=1 $GQ_URL

Shallow clone a specific branch

Perform the same shallow only on a specific branch.

git clone --depth=1 --single-branch --branch=$GQ_BRANCH $GQ_URL

Security & Access Control

About

An extensive collection of meticulously curated Git questions and answers

Topics

Resources

License

Stars

Watchers

Forks

Languages