In The Washington Post, Dana Milbank outlines the Republican incompetence that exacerbated the Coronavirus disaster:

“Trump depleted the government of scientific expertise and did little to heed warnings to prepare for a pandemic. He blocked Congress from conducting meaningful oversight. He repeatedly proposed cutting public health and medical research. The constant turnover and reliance on ‘acting’ officials eroded competence. His reckless stimulus legislation during an economic boom... left few fiscal and monetary tools to stop the ongoing economic panic. His constant stream of falsehoods misled the nation about the threat of the virus and contributed to a delayed, haphazard response. His administration badly misjudged the impact of the virus and was claiming until just a couple of weeks ago that it would require no additional government spending.”

Git Notes

Version control notes — Git 2.0

Git Notes

These are my Git notes, covering basic features of Git 2.0. If you find a mistake, please let me know.

This page includes a two-column print style. For best results, print in landscape, apply narrow margins, change the Scale setting in your browser’s print options to 70%, and enable background graphics. Firefox and Chrome each have their own set of printing bugs, but one of them usually works.

Contents

These are largely complete, but there is more to be written about merging, rebasing, and log options. Some day I will also add a quick reference for commonly-used actions. Check back later!

Overview

Commits

A Git repository stores project history as a series of commits. Each commit contains:

  • A snapshot that gives the state of the working folder at the time of the commit;
  • The author of the changes, and the author date, which tells when the changes were first committed or added to a patch;
  • The committer of the changes, and the commit date, which tells when the commit was last applied, rebased, or otherwise modified;
  • A commit message that describes the changes;
  • References to a number of parent commits from which the new snapshot is said to derive.

Snapshots

Unlike many version control systems, Git stores each version of a particular file in whole, rather than storing a series of differences. Snapshots are represented by a set of blob and tree files within the .git folder. Each blob stores the content of one file. Each tree lists the content of one folder, with files being represented by blobs, and subfolders by additional trees:

$ git ls-tree b623a43
040000 tree 579dc5d4713ce8632d8e7c2b335540f263a73ad5 Lib
100644 blob 2445c091a62c88085cf255e3e0c04e0163547050 Main.cpp
100644 blob b50e8a717d291406281093d10999b18d20d0287b Main.h

Every blob or tree has an object ID, a 160-bit SHA-1 hash of the object's content, which determines the object's location within the .git folder hierarchy. Changing a working file produces a new blob with a new ID. Each tree contains the object IDs of the files and subfolders in one folder, so changing a file also changes the tree's content, and therefore its own object ID. As a result, a change in the lowest levels of the folder hierarchy produces a new series of trees that uniquely identify the new snapshot. IDs are probabilistically unique, so blobs and trees from different snapshots can coexist within the .git folder, with common elements being shared between them.

Each commit also has an object ID. The full ID is a forty-digit hex number, but commits are commonly referenced by their first seven digits. Git can cryptographically sign a commit with GnuPG to prove that it originated from a particular source.

The index

The index defines the snapshot for the next commit:

$ git ls-files --abbrev --stage
100644 019f287 0        Lib/Rnd.cpp
100644 49aaef6 0        Lib/Rnd.h
100644 2445c09 0        Main.cpp
100644 b50e8a7 0        Main.h

Git also uses the index to detect changes in the working tree. Files in the index are said to be tracked. Though it resembles a tree, the index lists every file in the folder hierarchy, while only implicitly listing the folders themselves. Because folders are not explicitly tracked, empty folders cannot be committed.

Checking out a commit sets the working folder and the index to match that commit's snapshot. Local changes are then staged with the Git add, mv, and rm commands, which create blobs and trees within the .git folder, and then update or remove lines within the index. This means that modifications made after a file is staged will not be committed, unless the file is added again.

Branches

Commits can be arranged to form a commit graph that documents the project history:

Commit graph

Each arrow points from a child commit to one of its ancestors. A root commit is one with no parents. Usually, there is only one root, but it is possible for a repository to contain more. A branch is implemented as a reference to a commit, which is then called the branch tip. The branch as a whole contains the tip and all commits that contribute to it. This includes commits made before the branch was created. It also includes commits in parallel histories that were joined by a merge, so branches frequently overlap. By default, the first branch is called master.

The HEAD

The HEAD marks the user's location within the project history; it references a branch or a commit. The HEAD can be moved with the checkout command, which also updates the working folder. When HEAD is set to a branch, each new commit takes the branch's tip as its parent, then the branch reference is moved to the new commit, so that it becomes the tip. Because HEAD references the branch, it necessarily follows to the new tip. When HEAD is set to a commit, the user is said to be in the detached HEAD state. Because commits are not part of any particular branch, no branch is selected in this case. Additional commits can be added, and these will reference the current commit as their ancestor, but unless a branch is made to reference them, they will eventually be garbage-collected.

Commits before the HEAD are identified by appending a tilde and an optional number. HEAD~n references the nth commit before HEAD. HEAD~ is equivalent to HEAD~1.

Unreferenced commits

Deleting a branch removes the branch reference without deleting any commits, at least not directly. If a series of commits are no longer referenced by any branch, they will be deleted when Git collects garbage. The reset command can be used to move the branch to a previous commit, and this can also leave commits unreferenced.

Though these commits are no longer part of the commit graph, their existance is recorded in the reflog, which tracks the commits that have recently been referenced by the HEAD:

$ git reflog
80d518e (HEAD) HEAD@{0}: checkout: moving from master to HEAD~3
4c8ff10 (master, dev) HEAD@{1}: merge dev: Fast-forward
a6c290a HEAD@{2}: checkout: moving from dev to master
4c8ff10 (master, dev) HEAD@{3}: commit: Add Clip
2bcbcd9 HEAD@{4}: commit: Update FFT
a6c290a HEAD@{5}: checkout: moving from master to dev
a6c290a HEAD@{6}: commit: Update ZTrans
80d518e (HEAD) HEAD@{7}: commit: Remove Post
de4c279 HEAD@{8}: commit: Add Auto

As long as the commits are not garbage-collected, they can be retrieved with the reset command.

Remote repositories

Repositories are often cloned from other other locations, producing local copies that can be modified independently. Cloning creates a reference called a remote that links to the original repository, and other remotes can be added later. Adding a remote also adds remote-tracking branches to the local repository, one for each branch in the remote. By default, the first remote is named origin, so the main branch in the first repository typically produces a remote-tracking branch called origin/master:

Remote-tracking branch

Remote-tracking branches show the state of the remote branches when the remote was last accessed. Most local changes do not affect remote-tracking branches. Instead, they move automatically when Git fetches from the remote:

Remote-tracking branch after changes

This allows the local history to diverge without losing track of the remote state. Also, if the user checks out a branch that does not exist locally, and if its name matches that of a remote-tracking branch, Git will set configuration values that associate the new branch with the upstream branch on the remote. The new branch will start at the remote-tracking position. When the new branch is used to push or pull changes, Git will target the upstream branch automatically.

Note that the phrase tracking branch may be used in different ways. Some authors use it to reference the new branch. By contrast, the Git man pages rarely use the phrase without qualifying it, and when they do, they use it to reference the remote-tracking branch, not the new branch.

Sharing changes

Fetching updates the remote-tracking branches, and downloads the objects needed to complete the new history. Pulling causes a fetch to be performed, then it merges the relevant remote-tracking branch into the current branch.

When merging, if only one branch has changed, Git performs a fast-forward merge that simply adds the new commits, and advances the branch to the new tip. If both branches have changed, merging produces a merge commit. Git creates new, merged files where necessary, and a new snapshot that represents the project in its merged state. This commit claims both branch tips as its parents.

Pushing uploads new objects and merges the current branch into the remote, but only if a fast-forward merge can be performed. If it can't, the user must pull before pushing. After merging the remote changes, the user can push to produce a fast-forward merge.

Configuration

git config

Git settings can be changed with the config command:

git config setting [value]

If setting and value are specified, config updates that setting. If value is omitted, config prints the current value of setting. If setting does not exist, a blank line is displayed.

config supports these options, among others:

--local
Applies the command to the repository settings file. Local settings override global and system settings.
--global
Applies the command to the user settings file. Global settings override system settings.
--system
Applies the command to the system settings file.
-e
--edit
Launches an editor to edit the specified settings file, or the local file if no scope is specified.
-l
--list
Lists the settings in the specified file, or all settings in all files, if no scope is specified.
--unset
Removes a setting.

Local settings are stored in .git/config. Other configuration files vary by system.

Other config options allow setting names to be matched with regular expressions. It is also possible to associate multiple values with a single setting, even in the same file.

Basic setup

After installing Git, the user should store their name and e-mail in the settings. These values will be attached to commits:

git config --global user.name "Jane Smith"
git config --global user.email jane@example.com

By default, Git uses vi to accept certain input from the user. To replace vi with Windows Notepad:

git config --global core.editor notepad

Other editors can be used, but they sometimes require additional configuration.

Git can also be made to abbreviate commit IDs in the log, where they would otherwise be printed in full:

git config --global log.abbrevCommit on

Ignore files

Git can be made to ignore certain files by adding names and patterns to one or more ignore files:

  • Adding a .gitignore file to any repository folder causes the rules in that file to be applied to the folder and all the folders beneath it. .gitignore files in subfolders override those in parent folders.

    By default, .gitignore is considered to be a working file, so it will be added to the repository and shared with other users. An ignore file can itself be ignored by adding its name to its content.

    When creating a file, Windows Explorer requires a name before the extension. To specify a name like .gitignore, add a period before and after the file extension. Windows will discard the trailing period.

  • Rules can also be specified in .git/info/exclude. This file is not shared with other repository users.
  • A custom ignore file can be specified by assigning its name to the core.excludesfile setting:

    git config --global core.excludesfile ~/GitIgnore.txt
    

Ignore file comments begin with a pound sign. Matches are specified with glob patterns:

# Ignore files produced by the CGV process:
exec-cgv*.b??

Patterns that end with a slash match folders only; others match both folders and files. The 'root' folder for a particular glob is the folder that contains the ignore file, if that file is in the working tree. If the file is outside the tree, as .git/info/exclude is, the 'root' is the repository folder.

Prefixing a pattern with an exclamation point causes matching files to be included, even if they were ignored by a preceding rule, so long as the preceding rule does not cause any parent folder to be excluded. Re-included files are ignored again if a succeeding rule excludes them.

Finally, only untracked files are ignored. If a file is ignored after being staged or committed, it will continue to be tracked.

Custom commands

Within each settings file, the alias section stores command aliases. To create an alias, assign a command string to alias.cmd:

git config --global alias.logs "log -n 16 --pretty=oneline"

Note that git is not included in the string. Invoke cmd as if it were a Git command:

$ git logs
822ea8f (HEAD -> master) Add window manager
a7d1a7a Add Rnd library
b623a43 Create repository

Begin the command string with an exclamation point to have it executed in the shell.

It is also possible to define a new command by giving a script or other executable the name git-cmd, and then adding it to the git-core folder or the user's path. Like an alias, the command can then be invoked with git cmd.

Creating repositories

git init

New repositories are created with the init command:

git init [folder]

If folder is specified, that folder will be created, if necessary, and the repository will be initialized within it. If it is not specified, the repository will be added to the current folder. The folder need not be empty when the repository is created, and running init a second time will not damage an existing repository.

init supports these options, among others:

--bare
Normally, init creates a .git subfolder to store blobs, tree files, and other Git data. This option places Git files directly in the target folder, leaving no room for project files. This bare repository has no index, and cannot be used to check out. This is appropriate for a central repository that is meant to share work without itself being used for development. Bare repository folders are often given names that end with .git.
--shared
Ordinarily, files in the .git folder are writable only for the owner. This option causes the files to be writable for all users in the owner's group, and it also sets the receive.denyNonFastForwards flag, which prevents users from pushing any change that cannot be applied with a fast-forward merge. The option also supports variations that allow more specific control over permissions.

git clone

The clone command copies the content of a remote repository:

git clone source [folder]

It also sets the source repository as the remote origin, and creates remote-tracking branches for each branch in that repository. Then it checks out the HEAD branch.

source can specify the remote with a file path or a URL. Git can access the remote with SSH, HTTP/HTTPS, or its own GIT protocal. FTP/FTPS access is now deprecated.

If folder is specified, the command creates the folder, if necessary, and places the repository within it. If it is not specified, clone chooses the folder name itself.

clone supports these options, among others:

-o name
--origin name
Uses name for the remote, rather than the default, origin.
-b name
--branch name
Checks out branch or tag name after cloning, instead of the HEAD branch.
-n
--no-checkout
No branch is checked out after cloning.
--bare
Places Git files directly in the target folder, leaving no room for project files, like the corresponding option in git init.

Staging changes

git status

The current commit represents the state of the project at a particular time. The index shows the content that will be stored if a commit is made. The working folder contains the project as it is now, on the local machine. The status command facilitates staging by showing the differences between these sets:

git status

Differences between the commit and the index are produced by changes that have been staged. These are listed under 'Changes to be committed':

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   Bl.cpp
        modified:   Bl.h

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   FFT.h
        modified:   Bl.h

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        Auto.h

Differences between the index and the working folder are produced by changes that have not been staged. If a given file is tracked, it will be listed under 'Changes not staged for commit'. If a file has been changed, added, and then changed again, it will be listed under 'Changes to be committed' and 'Changes not staged for commit'. Files that have never been added will be listed under 'Untracked files'.

By default, status also shows the selected branch. The command supports these options, among others:

--ignored
Causes ignored files to be listed in a separate section.
-s
--short

Displays information in the 'short' format:

 M FFT.h
M  Lib/Bl.cpp
MM Lib/Bl.h
?? Auto.h

Before each file, characters give the index and working folder status, respectively.

git add

New or changed files must be added to the index to be included in the next commit. This is done with the add command:

git add [files]

add also creates blobs and new trees. It supports these options, among others:

-u
--update
Adds all tracked, changed files to the index, including deleted files. New files are not added.
-A
--all
Adds all changed files to the index, including deleted and new files.
-f
--force
Adds elements in files that would otherwise be ignored.
-p
--patch
Allows the user to stage changes interactively. If files are specified, Git steps through them, asking the user how to stage each particular file. Changes in a single file are grouped into hunks. The user can stage all hunks, or none, or only some of them. If files are not specified, all changed, tracked files are iterated.

git rm

Deleting a file in the shell and then adding it causes it to be removed from the index. Files can be deleted and the index updated in one step with the rm command:

git rm [files]

Each file is listed as it is removed:

$ git rm Win.*
rm 'Win.cpp'
rm 'Win.h'

The command can be applied to already-deleted files. It does not delete untracked files.

rm supports these options, among others:

-r
Removes all files from the specified folder, plus all files in contained folders, recursively.
--cached
Removes files from the index without deleting them in the file system.

git mv

Moving or renaming a file in the shell and then adding both the original and the new location causes it to be renamed or moved in the index. This can be done in one step with the mv command:

git mv old new

Note that reset will undo the change to the index, but it will not return the file to its original name or location in the file system.

mv supports this option, among others:

-f
--force
Move or rename the file even if there is already a file at the new location.

Retaining file history

Presumably, a file is moved in order to retain its place in the Git history. Git does not record file moves, however; it merely infers them when it displays the history. Unfortunately, some operations can prevent Git from completing that inference:

  • If the file content has not changed, status will describe the file as 'renamed' if it is moved with git mv, or if it is moved in the shell and added. If the file is then committed, the history will be retained.
  • If the file has changed significantly, and if it is moved in the shell and then added, Git will treat the moved file as if it were new, and the history will not be retained.
  • If the file has changed, and if it is moved with git mv but not added, status will describe it as 'renamed', yet the file in the new location will also be marked 'modified', and it will be listed under 'Changes not staged for commit'. Committing at this point will cause the move to be recorded in the history, but the changes will not be recorded. Adding the moved file after the first commit, and committing a second time will record the changes and retain the history.
  • If the changed file is moved with git mv, and if the new location is immediately added, status will no longer describe the file as 'renamed'. Instead, it will describe the original file as 'deleted', and it will list a 'new' file at the new location. If the file has changed significantly, committing at this point is not likely to conserve the history.

In general, it is safest to store content changes and moves as separate commits.

Unstaging files

Among its other uses, the reset command can return some or all of the index to its state as of the last checkout:

git reset [files]

If files are specified, only those files are unstaged; otherwise, the entire index is targeted. reset does not change files in the working folder.

reset supports this staging-related option, among others:

-p
--patch
Iterates and resets the staged files interactively, like the corresponding option in git add.

Neither files nor the --patch option can be combined with the --soft, --mixed, or --hard options described elsewhere.

Committing changes

The commit command creates a new commit that matches the content of the index, and then adds it to the current branch:

git commit [files]

The command is typically used without specifying files. If files are specified, they are committed even if they have not been staged, so long as they are tracked.

commit supports these options, among others:

-a
--all
Stages all modified, tracked files before committing.
-p
--patch
Selects and commits files interactively, like the corresponding option in git add.
-m msg
--message msg
Uses msg for the commit message. If this option is not used, Git launches an editor that accepts message input. The commit is processed when the editor closes.
-C commit
--reuse-message commit
Reuses the message in commit.
--amend
Causes the new commit to replace the one at the tip of the branch, rather than adding to the branch. As usual, the index matches the last commit immediately after that commit was made, so changes have been staged relative to the commit that will be replaced, not the commit that will precede the replaced commit in the history. If nothing is staged, the new commit will have the same content, with a possibly different message. If no message is specified, the tip message will be displayed in the editor for modification or reuse.

Branching

git checkout

The checkout command can be used in different ways. Most often, it targets a branch or a commit:

git checkout [target]

This form moves the HEAD to the target, and then updates the index and working folder to match the associated snapshot. If no target is specified, the HEAD is checked out.

If the working folder contains tracked, modified files, and if those files are not tracked in target, or if their content in target differs from their content in the current commit, the command fails, since updating them would lose the changes.

checkout supports these options, among others:

-f
--force
Proceeds with the checkout, even if this causes changes in the working folder to be lost.
-m
--merge
Proceeds with the checkout, even if changes in the working folder conflict with target. For every file that does conflict, a three-way merge will be performed, with conflicts being marked in the file. The merge is completed by editing each file and then staging it, or by explicitly removing it with git rm.
-b name
Creates the specified branch at target before checking it out. The command fails if the branch already exists.
-B name
Creates the specified branch at target before checking it out. If the branch already exists, it is moved to the target.
-t
--track

Creates and associates a branch with the remote-tracking branch target. If the -b option is specified, that name is applied to the new branch. Otherwise, the name derives from the remote-tracking branch.

This is done automatically after attempting to check out a branch that does not exist, if a remote-tracking branch has the same name.

Checking out specific files

checkout can also be used to update specific files in the working folder:

git checkout [commit] files

If a commit is specified, the files are drawn from that commit, and they are also updated in the index. If a commit is not specified, the files are drawn from the index, and they are updated in the working folder only. If staged changes conflict with the checkout, the command will fail. Unstaged changes are overwritten without warning.

One checkout option is specific to this form:

-p
--patch
Instead of being overwritten, files with unstaged changes are merged interactively, like the corresponding option in git add.

git branch

Branches can be managed with the branch command. When no branch name is specified, the command lists branches. The current branch is marked with an asterisk:

git branch

In this mode, branch supports these options, among others:

-r
--remotes
Lists only remote-tracking branches.
-a
--all
Lists ordinary branches and remote-tracking branches.
-v
--verbose
Displays the object ID and commit message for each tip within the branch listing.
-vv
Displays the object ID and commit message for each tip within the branch listing, along with the name of the upstream branch, if any.
--contains [commit]
Lists branches that count commit among their ancestors. If no commit is specified, branches that descend from the HEAD are listed.
--no-contains [commit]
Lists branches that do not count commit among their ancestors. If no commit is specified, branches that do not descend from the HEAD are listed.
--merged [commit]
Lists branches that are ancestors of commit, or of the HEAD, if no commit is specified. These are branches that have been fully merged to the commit.
--no-merged [commit]
Lists branches that are not ancestors of commit, or of the HEAD, if no commit is specified. These are branches that have not been fully merged to the commit.

Branches can also be created, edited, or deleted with this command:

git branch name [position]

Unless an option indicates otherwise, this form creates the specified branch at position, or at the HEAD, if no position is specified. The position can be given as a commit, a tag, or another branch. The new branch is not checked out.

When used this way, branch supports these options, among others:

-m [name] new
--move [name] new
Renames branch name, or the current branch, unless a branch with the new name already exists.
-M [name] new
Renames the branch even if a branch with the new name already exists.
-c [name] new
--copy [name] new
Copies branch name, or the current branch, unless a branch with the new name already exists.
-C [name] new
Copies the branch even if a branch with the new name already exists.
-d
--deletes
Deletes the branch. The operation fails if the branch has not been fully merged to the current branch, or to the upstream associated with the branch to be deleted. A branch is fully merged if its tip is an ancestor of a second branch tip, so that the second contains every commit in the first.
-D
Deletes the branch even if it has not been fully merged.
-f
--force
Moves the specified branch to position, or to HEAD, if no position is specified. Also allows copy, move, and delete operations to proceed even if another branch would be overwritten, or if the target branch is not fully merged.
-t
--track
Associates the new branch name with the remote-tracking branch position.

Branches can be created and checked out in one step with the -b option of the checkout command:

git checkout -b name

Editing the history

git reset

As already seen, the reset command can be used to unstage some or all of the staged changes. It can also be used to move the current branch to a particular commit, and, optionally, to update the index, or the index and the working folder:

git reset [commit]

If a commit is specified, the current branch is moved to that commit. If HEAD references that branch, it follows the branch as it moves. If no commit is specified, the command targets HEAD.

reset supports these modes, which are not compatible with the --patch option, or with the files argument that is used to unstage specific changes:

--soft
Moves the branch without updating the index. Changes committed or staged since the target commit will remain staged after the reset.
--mixed
Moves the branch and updates the index. This is the default mode. Changes made since the target commit will persist in the working folder, but they will not be staged.
--hard
Moves the branch, updates the index, and changes all working files to match the target commit, including those with unstaged changes. Untracked files are not affected.
--merge
Moves the branch, updates the index, and changes some working files to match the target commit. Files that changed between the current commit and the target commit are updated, as are files with staged changes. Files that did not change, and that now contain unstaged changes are not updated. If any file changed between the commits, and now contains unstaged changes, the operation will fail.
--keep
Moves the branch, updates the index, and changes some working files to match the target commit. Files that changed between the current commit and the target commit are updated. Files that did not change, and that now contain staged or unstaged changes are not updated. If any file changed between the commits, and now contains staged or unstaged changes, the operation will fail.

git revert

The revert command creates a new commit that undoes the changes in the target commit, and all the commits that follow it:

git revert commit

This reproduces the snapshot of the commit just before the target, but in a different commit, with different metadata. The reverted commits remain in the history. All working files are updated to match the new snapshot, except those with unstaged changes, which are unaffected. The operation fails if any changes have been staged.

revert supports this option, among others:

-n
--no-commit
Updates the working files and the index, but does not add the new commit. All working files are updated to match the new snapshot, except those with changes, whether staged or unstaged. Staged changes do not cause the operation to fail.

Sharing work

git fetch

The fetch command updates the tags and remote-tracking branches associated with another repository, and downloads the objects needed to complete the updated history:

git fetch [remote] [target]

target can specify a branch or a tag. If neither remote nor target are provided, fetch targets the remote associated with the upstream that is tied to the current branch, or origin, if there is no upstream.

fetch supports these options, among others:

--all
Fetches from all remotes.
-p
--prune
Also removes remote-tracking branches referencing branches that have been removed from remote.

git pull

The pull command fetches from another repository and then merges changes to the current branch:

git pull [remote] [target]

As in the fetch command, target can specify a branch or a tag. If neither remote nor target are provided, the fetch targets the remote of the upstream associated with the current branch, or origin, if there is no upstream.

By default, unless the operation can be completed with a fast-forward merge, pull adds a merge commit to the history to represent the new, merged state.

pull supports these options, among others:

--all
Fetches from all remotes before merging.
--no-commit
Fetches and merges as normal, then stages any merged files, but does not create the merge commit. Committing immediately after this operation produces an equivalent merge commit.
--squash
Fetches changes and updates the working files and index as if a merge had been performed, but without recording a merge. Where a merge commit would claim both branch tips as parents, committing immediately after this operation produces an ordinary commit with only the current HEAD as its parent.
-r
--rebase[=mode]

Fetches remote changes and then rebases local changes into one or more commits that follow the pulled commits. The rebase can be controlled by specifying a mode:

  • true causes local commits to be reimplemented as an equal number of new commits. This is the default mode when the --rebase option is used.
  • interactive starts an interactive rebase. Local commits are displayed in an editor, allowing each to be picked, squashed, edited, or dropped.
  • false causes changes to be merged rather than rebased. This is useful when a branch has been set to rebase by default.
--ff-only
Cancels the pull if it cannot be completed with a fast-forward merge.
--no-ff
Creates a merge commit even if a fast-forward merge could be performed.
-e
--edit
Launches an editor, allowing the user to change the message for the merge commit, if any.

git push

The push command updates remote branches and tags, after uploading the objects necessary to complete the new history:

git push [remote] [branch]

If no remote is specified, Git reads it from the branch.name.pushRemote, remote.pushDefault, or branch.name.remote setting, with name being the current branch. Otherwise it pushes to origin.

If a branch is specified, the command pushes to that branch. If not, Git reads it from the remote.name.push setting, with name being the current branch. Otherwise, the outcome depends on the value of the push.default setting:

  • current pushes from the current branch to the remote branch with the same name.
  • upstream pushes from the current branch to that branch's upstream branch.
  • simple pushes from the current branch to that branch's upstream branch, but only if they share the same name. This is the default in Git 2.0.
  • matching pushes every local branch with a name that matches a branch on the remote. This was the default before Git 2.0.
  • nothing causes the push to fail if no target is set.

The push fails if it cannot be completed with a fast-forward merge. This is generally resolved by pulling and then pushing again.

push supports these options, among others:

--all
Pushes all branches.
--tags
Pushes all tags, in addition to the specified branch.
--delete
Removes branch from the remote.
--prune
Removes every remote branch that does not have the same name as a local branch.
-u
--set-upstream
Creates a remote-tracking branch after pushing branch to the remote, and sets the remote branch as the upstream of branch.

Miscellanea

File globs

Many Git commands allow files to be specified with glob patterns. Within a glob, certain character sequences are expanded to match multiple files:

Sequence Effect
? Match any one character.
* Match any sequence of zero or more characters.
[set] Match any one character in set.
[start-end] Match any one character between start and end, inclusive.

Globbing is performed first by the shell, and then by Git. Ordinarily, the shell's globbing leaves no wildcards to be expanded by Git, but a wildcard can be hidden from the shell by escaping it with a backslash:

git add \*.dat

The shell knows only about files in the file system, whereas Git knows those files plus the files in its index. Escaping a wildcard therefore allows different files to be targeted by the glob.

Sources

Git man pages
git-scm.com
Retrieved March 2018

Git Pocket Guide
Richard E. Silverman
2013, O'Reilly Media Inc.

Ry's Git Tutorial
Ryan Hodson
2014, RyPress

Pro Git
Scott Chacon and Ben Straub
2014, Apress Media LLC

Working with dates in Git
alexpeattie.com
Retrieved March 2018

Stack Overflow
git ignore exception not working as desired
Retrieved February 2020