Skip to content

Instantly share code, notes, and snippets.

@asemarian
Last active September 1, 2023 15:06
Show Gist options
  • Save asemarian/bc565ddffb4e0e5ce0e8b684e652df0d to your computer and use it in GitHub Desktop.
Save asemarian/bc565ddffb4e0e5ce0e8b684e652df0d to your computer and use it in GitHub Desktop.
A quick summary of the essential Git commands

Basic Terminology

  • Commit: a snapshot that captures the state of your project at a particular point in time.
  • HEAD: a pointer that usually points to the tip of the currently checked out branch.
  • Branch: a series of commits with a pointer that points to the most recent one.
  • Working directory: the local workspace hosting your entire project files and directories and where you experiment with new changes.
  • Staging area: a place where changed files are added before they can be part of the next commit.
  • Repository: the hidden .git directory that is created and used by Git to keep track of changes to your files.
  • Remote: the name of a pointer, typically named "origin," that points to the URL of a cloud-hosted repository.

Getting Started

Set up your name and email address:

git config --global user.name "John Doe"
git config --global user.email "john@email.com"

Set up Visual Studio Code as the default text editor:

git config --global editor.core "code --wait"

Initialize a new Git repository:

git init

Clone an existing Git repo:

git clone <url>

Snapshotting

git status

Show the current state of your repository.

Run git status -s to see the output in a shorter format.

git add <file1> <file2> ...

Add changed files or previously untracked files from the working directory to the staging area. Use git add . to add all files at once.

git commit -m "commit message"

Create a new commit with files that are currently in the staging area.

To add a separate commit message that explains in more detail the changes in your commit, run: git commit -m "commit message" -m "another commit message".

You can add all tracked files and commit them in one go by running git commit -am "commit message". This only works if you're committing files that are already tracked by Git.

To add new changes to the most recent commit instead of creating a new one, or to modify the commit message run git commit --amend or git commit --amend -m "new commit message" after staging your new changes if there are any.

To create an empty commit, run git commit --allow-empty -m “commit message”.

git log

Show a log of commits for the current repository along with the current position of HEAD (which commit it points to).

A useful variant is git log --oneline which shows a shortened commit hash alongside the commit message.

You use the --grep option to search for commits that contain a specific string in their commit message. For example: git log --grep="commit message".

You can limit your search to a specific number of commits by using the -n flag: git log --grep="commit message" -n 5.

And you can also use -i flag to make the search case-insensitive.

Branching

git branch <name>

Create a new branch called <name> based on the currently checked out branch.

git branch

Get a list of all branches in the current repository.

You get the same output by running git branch --list.

git switch <branch> or git checkout <branch>

Switch to an existing branch named <branch>.

git switch -c <branch> or git checkout -b <branch>

Create a new branch <branch> and then switch to it. This effectively combines git branch <branch> and git switch <branch>.

git branch -d <branch>

Delete the branch named <branch>. You can force delete it by using the -D flag.

You can delete multiple branches by listing them: git branch -d <branch1> <branch2> <branch3>.

You can't delete a branch if it's currently checked out. You have to switch to a different branch first.

git branch -m <new-name>

Rename the currently checked out branch to <new-name>. To rename a different branch: git branch -m <old-branch-name> <new-branch-name>.

git checkout

git checkout is a versatile command that can be very useful sometimes. These are some of the ways you can use it:

  • git checkout <commit>: this goes into detached HEAD mode by making HEAD point directly to the commit that you specify (instead of pointing to the tip of a branch). In this mode, you can view and make changes and at any point you may revert your changes by running git switch <branch> or git switch - to switch to the branch HEAD was pointing to before using the checkout command. If you'd like to keep the changes you make in detached HEAD, you can run git switch -c <branch> to create a new branch with your new changes.
  • git checkout HEAD~n: check out the nth ancestor commit of HEAD.
  • git checkout HEAD <file> or git checkout -- <file>: discard staged and unstaged changes to match HEAD. Similar to running git restore, explained below.

Merging

There are two steps required in merging:

  1. First, you switch to the branch you want to merge changes into.
  2. Then you run the merge command.

For example, to merge feature branch into main:

git switch main
git merge feature

Some useful options:

  • To show a list of branches that have been merged into the currently checked out branch: git branch --merged
  • To show a list of branches that have not yet been merged into the currently checked out branch: git branch --no-merged
  • To merge changes in feature branch into main but using only a single commit: git merge --squash main. All commits from the branch will be squashed into a single commit. You’ll see all changes have been staged and you’ll have to manually create a new commit.

Fast-Forward Merge

In most cases, the merge will be a fast-forward merge: the base branch (main) pointer will simply be updated to point to the same commit that the merged branch (feature) points to.

Non-Fast-Forward Merge

Sometimes the merge isn't exactly straightforward. This happens when two branches diverge.

Suppose that you create a new branch based on main and call it feature. Let's say that you add a couple of new commits on feature and at the same time there's a new commit on main that you currently don't have. When you try to merge, Git will create a new merge commit.

You can manually create a merge commit by running git merge --no-ff <branch>. This helps you maintain a clear history of when a branch was merged into another branch.

Resolving Merge Conflicts

Merge conflicts happen when the same part of the file is modified differently on the two merged branches. When this happens, Git will let you decide what to keep and what to remove.

Merge conflicts are resolved manually. Adding files using git add <file> tells Git that conflicts have been resolved.

Run git merge --abort after a merge has caused conflicts to return to the pre-merge state. It's important to note that there is no guarantee that uncommitted changes will be reconstructed by running this command.

After resolving conflicts and adding files to the staging area, you may create a commit manually or run git merge --continue to be prompted for a merge commit message.

Cherry-Picking

You may use git cherry-pick to merge specific commits from one branch to another.

For example, if you want to merge <commit-hash> from the branch main to the branch feature, you run the following:

# swtich to the target branch first
git switch feature
# now run the cherry-pick command
git cherry-pick <commit-hash>

Running this command may cause merge conflicts. You can resolve them normally. You get the familiar abort and continue options as you do with regular merges.

Comparing

git diff

Show the difference between the working directory (the current state of your files) and the staging area. In other words, this shows you changes to your working directory that you could add to the staging area by running git add .. The git diff command accepts different options and arguments:

  • git diff --staged or git diff --cached: show changes that have been staged relative to the most recent commit.
  • git diff HEAD: list all changes, staged and unstaged, since the last commit.
  • git diff <file1> <file2>: show working directory changes to specified files.
  • git diff <branch1> <branch2>: compare the tip of branch1 to the tip of branch2.
  • git diff <commit1> <commit2>: compare changes between the given commits (which are passed as commit hashes).
  • git diff --staged <commit> <file> : show changes that have been staged for file <file> since the commit <commit>. It basically answers the question: how is <file> going to be different in the next commit compared to the old commit <commit>?

Stashing

Let's say you have some incomplete work on a feature and right now you really want to work on a different feature altogether. You don't want to finish working on that now, and your changes are not yet ready to be committed. What do you do in this case? You stash, of course.

You can stash as many times as you like. Your changes are saved to a stack-like data structure where the top entry is the most recent.

git stash

Stash away the current changes (staged and unstaged) and get back to a clean working tree matching the most recent commit. git stash push does the exact same thing.

There are several variations on the basic stash command:

  • git stash --keep-index: stash only unstaged changes, keeping staged changes intact.
  • git stash -p: interactively choose which chunks of changes to stash.
  • git stash push <file1> <file2>: stash changes made to the provided file paths in one stash entry.
  • git stash list: show a list of stashed changes.
  • git stash pop: reapply the most recently stashed changes to the working directory and remove them from the stash.
  • git stash apply: reapply the most recently stashed changes to the working directory without removing them from the stash
  • git stash apply n: reapply stashed changes saved at index n.
  • git stash drop n: drop/delete stashed changes saved at index n.
  • git stash clear: clear all stashed changes.

Undoing

git restore <file>

Discard unstaged changes made to <file> and restore its state to the most recent commit. You can specify multiple files git restore <file1> <file2> or all files git restore ..

You can also remove staged changes by using the --staged option.

git reset <commit>

Reset the current branch to a particular commit and keep the changes in the working directory. If you'd like to discard the changes, simply use the --hard option.

Warning: any changes you discard with the --hard option are permanently removed, so this should be used sparingly.

git revert <commit>

Create a new commit to undo the changes from an earlier commit.

To undo the effects of a revert, you can revert the revert commit. If there have been changes since the revert commit, you'll have to resolve conflicts.

This is the command to use—instead of git reset—when you want to undo changes that have already been shared with other collaborators on the same project.

If you use git reset to undo changes that have already been shared, you'll have to force push your changes to the remote repository. This will overwrite the history of the remote repository and could potentially cause problems for others.

Collaborating

GitHub, BitBucket and similar websites make it easy to share code and collaborate on projects. Git has several commands to make this possible.

git clone <url>

Use this to clone an existing repository hosted on GitHub or a similar website. When using this command, the remote is set automatically for you.

git remote add <name> <url>

Sometimes you create a new local repository and then you want to add a "remote" repository to push changes to.

"Origin" is a typical name for a remote repository. For example: git remote add origin https://github.com/yourUsername/yourRepoName.git.

  • To show a list of remotes: git remote
  • To show a list of remotes with URLs: git remote -v
  • To rename an existing remote: git remote rename <old-name> <new-name>
  • To remove a remote: git remote remove <name>

git push <remote> <branch>

Push committed changes from your local branch to your remote branch. If no arguments are given, <remote> defaults to "origin" and <branch> defaults to the current branch. To push all branches, use the --all option.

  • To show a list of remote branches: git branch -r.
  • To show a list of all branches, including remote branches: git branch -a.
  • To create a local branch from a remote branch: git switch <branch>.

git fetch <remote> <branch>

Get the latest changes from the remote repository without merging them locally. If no arguments are given, <remote> defaults to "origin" and <branch> defaults to the current branch.

git pull <remote> <branch>

Fetch changes then merge them locally. This is equivalent to running git fetch then running git merge. With no arguments, <remote> defaults to "origin" and <branch> defaults to currently checked out branch.

Rebasing

git rebase can be used in two ways.

As an alternative to git merge

As an example, let's suppose that you created a new branch, <feature>, based on main. While you were working on your new feature, new changes have been added to the main branch. You want to pull these changes and merge them. But you can use rebase in this case.

First, switch to your branch: git switch <feature>. Now run git rebase main to rebase your branch commits on the latest changes from main. This command will create new commits to make a linear commit history but these new commits will keep their original metadata, such as author name and date.

Warning: do not rebase commits that you've already shared with other team members. This should only be used locally on changes you haven't shared yet. Otherwise, you'll have to force push your changes to the remote repository which will overwrite the history of the remote repository and cause problems much like what happens when you use git reset instead of git revert.

As a way to clean up your commit history

Do you want to delete, squash, rename, or reorder your commits before sharing them? Use interactive rebase for that.

git rebase -i HEAD~n

Running this command will launch your default editor with instructions on what each command does. You must specify how far back you want to go in your commit history by specifying HEAD~n.

Note: git rebase uses git cherry-pick behind the scenes and that might mean that you’ll get more conflicts than when using a regular git merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment