Git and Magit Basics

I'm not a huge fan of git's CLI or its documentation, This page exists to remind of the basics whenever I forget them, which is basically always.

Local, remote, clone, fork

A git repo can be standalone or it can be associated with one or more remote repos, which acts as a source and destination for commits. You can create a local, standalone repo by running

git init

On the other hand, if you create a local git repo via a git clone command

git clone <URL>

then a remote repo is set up to point to the URL cloned from. By default the command will give the remote repo an easy to remember name like origin but you can change that behaviour with the -o or --origin option:

git clone -o <name> <URL>
git clone --origin <name> <URL>

You can check your remote repos with this command:

git config remote.$(git config branch.$(git symbolic-ref --short HEAD).remote).url

And you can add a remote (called origin in this example) after the fact by doing this:

git remote add origin <URL>


Forking isn't a concept in git, but rather a concept in github and other similar code sharing platforms.

Normally, if you want to contribute to a project on github, you have a couple of options.


git push -u origin master
git push --set-upstream origin master

To check the status of a repo

git status 

will give you a summary of what's changed in the repo.

git status -s 

will give a useful shorter summary, with M, A, R telling you what's been modified, added, removed. Two columns are shown, telling you the status with respect to the index and to the working directory.

Getting diffs

git diff 

will give you a diff between your working directory and the index, while

git diff --staged

will give you the diff between your index and the repo, while

git diff HEAD

gives you the diff between the working directory and the latest commit. This is probably the closest thing you have to hg diff.

All of these will dump the diff to stdout. You can configure another tool by doing adding the following line to your "~/.gitconfig":

    external = 

Where you have to configure a special script because git calls it like this:

script "path", "old-file", "old-hex", "old-mode", "new-file", "new-hex", "new-mode"

But that means that all your diffs will use this script, which is possibly not what you want. So got offers another kind of diff, called difftool:

git difftool

which is specifically designed for viewing diffs when the standard one won't do. You configure it like this

    tool = <tool>

Git offers a range of difftools pre-configured "out-of-the-box" (kdiff3, kompare, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, diffuse, opendiff, p4merge and araxis), and also allows you to specify your own.

Good article here:

One other thing: I usually like to

  1. get a directory diff before looking at the individual diffs and b. avoid the tool prompts

You can get the former with -d and the latter with -y, like this:

git difftool -d -y

And remember that difftool takes the same arguments as diff, so add a HEAD if you want the difference between the working directory and the last commit:

git difftool -d -y HEAD

If you like using meld:

git difftool --tool meld --staged -y -d

Undoing an add

To undo the add to the index, use

git reset HEAD <file>

Undoing a commit

To undo the last commit, use

git reset --soft HEAD~1

(reset will move the branch pointer to HEAD~1, which is the commit right before HEAD. The --soft makes ure everything in your working directory remains intact)

Bare Repositories

git has a notion of bare repositories. Bare repositories are repositories that contain no files, just the metadata.

You create a bare repository by use the --bare option during git init or git clone.

By default you can only push to a bare repository. That's why it's important to know about them. Pushing to a non-bare repo is considered weird because you won't be at the tip when you do so. Your working directory will be out of sync with your metadata.

In mercurial, this doesn't seem to be considered as weird. You push to the remote repo, and the remote repo has to do a hg update to get the latest changes.

Anyway, you can still push to a non-bare repo, you just have to configure it to do so. On the remote repo, you have to run this:

git config receive.denyCurrentBranch ignore

That will set up the non-bare repo to accept changes.

Stripping changesets

The equivalent to

hg strip <changeset>

in git is

git reset --hard <changeset>
git gc --prune=now

Basic commands

To rest the state of your working directory:

git reset --hard

To clean all untracked files :

git clean -f

To clean all untracked files including directories

git clean -fd

To clean all files, including ignored ones:

git clean -xf

To stage all changes and new files :

git add .

But to stage all changes, including removed files:

git add -A

Good resource:


To create and switch to a branch

git checkout -b new-branch

Switch back to master:

git checkout master

Merge the commits from the previous branch:

git merge new-branch

Delete the old branch:

git branch -d new-branch

GitBasics (last edited 2020-11-03 23:06:29 by DesmondRivet)