Last active
May 10, 2023 17:41
-
-
Save fpl9000/1a67aebdb0237a13fa15 to your computer and use it in GitHub Desktop.
Git Cheat Sheet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Git Cheat Sheet | |
Author: Fran Litterio <flitterio -at- gmail.com> | |
Things to do: | |
- Show Git commands throughout the 'Basic Concepts' and 'Advanced Concepts' sections. | |
- Stashing: https://git-scm.com/book/en/v2/Git-Tools-Stashing-and-Cleaning | |
- Revision specification syntax: https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection | |
- man gitrevisions | |
- Reflog syntax: HEAD@{n}, HEAD@{yesterday}, HEAD@{2.months.ago}, ... | |
- Ancestry References: foo^, foo^2, foo~, foo~2, foo^2~3, ... | |
- Commit ranges: foo..bar, foo...bar | |
- Reverting changes with 'git restore ...' | |
- Reverting commits | |
- Rebasing | |
- Squashing | |
- Refspecs & reference namespaces: https://git-scm.com/book/en/v2/Git-Internals-The-Refspec | |
- How to create a remote repo | |
- Porcelain vs plumbing | |
- Detached HEAD | |
================================================================================ | |
Contents | |
================================================================================ | |
This document has the following top-level sections: | |
- Git Documentation | |
- Basic Concepts | |
- Advanced Concepts | |
- Git Command Quick Reference | |
================================================================================ | |
Git Documentation | |
================================================================================ | |
The Git documentation includes a reference manual, a tutorial, and videos. You can find it at: | |
- https://git-scm.com/doc | |
If you're new to Git, start with the book "Pro Git", which can be read online at: | |
- https://git-scm.com/book | |
If you're already familiar with Git, the Git reference manual is at: | |
- https://git-scm.com/docs. | |
The Git reference manual is available interactively using command 'git help COMMAND'. Type | |
'git help' for a usage summary. | |
On UNIX/Linux systems, every Git command has a man page named "git-COMMAND", where COMMAND is | |
the Git command name. | |
================================================================================ | |
Basic Concepts | |
================================================================================ | |
A Git repository (called a "repo") is a directory tree containing a mix of revision controlled | |
files and other files. | |
- The revision controlled files are said to be "tracked" by Git. All other files in a repo | |
are "untracked". Tracked and untracked files exist alongside each other in the repo. | |
- Git metadata is stored in directory .git in the root of the repo. Rarely, you might look | |
at the .git directory, but generally you should ignore it. | |
- A repo contains one or more branches, each containing a different history of the files in | |
the repo. | |
- The main branch is named "master" by default, but you can choose any name for a branch. | |
Branches can be renamed at any time. People refer to the "master branch" even if its | |
name isn't "master". | |
- Unlike most revision control systems, Git branches are not represented by separate | |
directories. Instead, you can only see the tracked files from one branch at a time. | |
- To work on files in a different branch, you have to switch to that branch. This | |
switching operation is called a "checkout" of the branch. This use of the term | |
"checkout" differs from what most revision control systems mean by that word. | |
For each branch, tracked files can exist in the following places: | |
WORKING FILES <-> INDEX <-> LOCAL REPO <-> REMOTE REPO | |
- Above, the bidirectional arrows show how Git workflow copies tracked files between these | |
places. It's important to understand this workflow when using Git. Let's look at how | |
each of these places is used and when tracked files are copied between them. | |
- WORKING FILES are tracked files that you can work on. You create, modify, and delete | |
working files. | |
+ Only one branch's tracked files are visible at a time. Those are the working files. | |
+ Use command 'git checkout BRANCHNAME' to switch to another branch. This changes the | |
working files to the other branch's tracked files -- except for any modified tracked | |
files, so be careful not to have any, otherwise you'll be left with a mixture of | |
tracked files from different branches. Git warns you if this happens. | |
+ Depending on how different the two branches are, a checkout can cause existing | |
working files to disappear, new working files to appear, and the contents of working | |
files to change. Directories that contain working files can appear and disappear | |
too. | |
+ Other revision control systems use the term "checkout" to mean "obtain permission to | |
modify a tracked file". Git has no such concept, because Git is decentralized. | |
There is no central authority to grant that permission. You are free to edit, add, | |
and delete any working file in your repo. | |
+ When you checkout another branch, your untracked files don't change, because Git | |
generally ignores untracked files. | |
* This can be confusing if your tracked files contain source code, because | |
compiler-generated binaries are untracked files. After you switch branches, your | |
source code will likely change, but the untracked binaries will not change, | |
causing them to be out-of-sync with your source code. | |
* One way to avoid switching between branches in a local repo is to use a separate | |
local repo for each branch. All branches still exist in all local repos, but | |
each local repo has a different branch checked out. | |
* Using separate local repos also avoids the problem where modified tracked files | |
are not switched when you switch branches, because you don't need to switch | |
branches. | |
- The INDEX is a compressed copy of all tracked files in the current branch. When you | |
checkout another branch, the index changes just as the working files do. | |
+ The index seems redundant. Why have two copies of the tracked files: the working | |
files and the index? Because the working files are for you to modify and delete. | |
The index is Git's copy of the current branch's tracked files. In a centralized | |
revision control system, the role of the index is filled by the central database, but | |
there is no such thing with Git. | |
+ As you make changes to the working files, you can "stage" the modified, new, and | |
deleted working files into the index. This is how you give your changes to Git. Use | |
command 'git add FILE ...' to stage new or modified files, and command 'git rm FILE | |
...' to stage deleted files. | |
+ Staged changes wait in the index to be part of a future "commit" into the current | |
branch in the local repo. Typical workflow is to stage a series of related changes | |
into the index, then later commit all of them at once to the local repo. | |
+ A file can be staged repeatedly. A more recently staged file replaces the previously | |
staged copy in the index. After a file is staged, the copy in the working files and | |
the copy the index are identical, until you make more changes to the working file. | |
+ For convenience, files can be staged and committed in one operation. However, | |
staging many related changes and then making a single commit keeps the repo's commit | |
history uncluttered and simplifies reverting changes. | |
+ The contents of the index are often called the "staged files", but don't take this to | |
mean that the index contains only files you have staged. The index contains all of | |
the tracked files in the current branch, including the changes you have staged. | |
+ The index is stored in the .git directory, along with the rest of the metadata for | |
your local repo. | |
- The LOCAL REPO is a compressed copy of all commits in all branches along with their | |
historical time-ordering. | |
+ The local repo contains the history of ALL commits in ALL branches. | |
+ The local repo exists on the computer where you do your work. Git is a distributed | |
revision control system, so each collaborator has a copy of every commit in every | |
branch in their local repo. There is no central database. | |
+ The local repo (and the index) are accessed through the filesystem, which lets you do | |
the majority of operations offline. | |
+ The local repo is stored in the .git directory, but people often use "local repo" to | |
mean the directory containing all of the working files plus the .git directory. | |
- The REMOTE REPO, often called a "remote", is for sharing work with other people. | |
+ The working files, the index, and the local repo are all located on your computer | |
under the same directory, but the remote repo usually exists on a server, so it can | |
be accessed by multiple people. | |
+ Collaborators on a project each have their own local repo (and its associated index | |
and working files), but they all share a common remote repo. A single-user project | |
doesn't need a remote repo, because there are no collaborators. | |
+ People usually don't work in a remote repo, but it is possible. | |
+ Git workflow copies tracked files between the working files, the index, the local | |
repo, and the remote repo (if present). So it's possible for a tracked file to be | |
different in each of these places. Also, the file may be different in your | |
collaborators' local repos. | |
To use Git you need a local repo. | |
- There are three ways to create a local repo: | |
+ Initialize a local directory. Do this if you already have the files you want to put | |
under revision control. | |
+ Clone a remote repo. Do this if you need to work on files that are already under | |
Git's revision control. | |
+ Copy an existing local repo. More on this below. | |
- You initialize a local directory with command 'git init'. | |
+ Command 'git init' creates the .git directory, creates some Git metadata in the .git | |
directory, and leaves you with no tracked files, no working files, an empty index, | |
and an empty local repo. | |
+ After you initialize a local repo, you are ready to stage and commit new files. | |
+ If the directory was not empty when you initialize it, the files in it remain as | |
untracked files. | |
+ A newly initialized local repo has no associated remote repo, but it can be given one | |
at any time (more on this later). | |
- You clone a remote repo with command 'git clone REMOTEURL', where REMOTEURL identifies a | |
Git remote repo on a server. For instance, https://github.com/torvalds/linux.git | |
identifies the Linux kernel's remote repo. | |
+ After you clone a remote repo, the new local repo contains a copy of every branch in | |
the remote, with the working files and index matching the remote's current branch | |
(usually the master branch). | |
+ Cloning connects the local and remote repos. This enables you to share work with | |
collaborators who have cloned the same remote repo. | |
+ After you clone a remote repo, the remote is called the "origin" of the local repo. | |
The local repo remembers which remote is its origin. | |
- A less common way to create a local repo is simply to copy someone else's local repo. | |
+ This works best if the other person's local repo has no staged files in the index and | |
no modified working files, otherwise your copy will have them too, which is probably | |
not what you want. | |
+ This works because there is no per-user information in a local repo. Your personal | |
Git configuration data is stored in file .gitconfig in your home directory (on UNIX) | |
or in an OS-designated personal folder (on Windows and MacOS). | |
+ You can make copies of your own local repo. This allows you do any of the following: | |
* You can have different branches checked out at the same time, so you don't have | |
to do 'git checkout BRANCHNAME' to switch one local repo between branches. | |
* You can do work on multiple computers. You can have a copy of a local repo on | |
both your personal laptop and your work computer. If you change the same file in | |
both repos, you will eventually have to merge those changes (see below for info | |
on merging). | |
* You can easily migrate a local repo to another computer: just copy it to the | |
other computer, delete the original, and pick up where you left off. | |
A repo contains branches. A branch contains commits. A commit contains a snapshot of a | |
branch's files at one point in time. | |
- You create a commit with command 'git commit', which commits all staged files in the | |
index. This copies the staged files into the local repo, along with some metadata. | |
+ The commit command spawns an editor for you to enter a commit message. If you prefer | |
to give the commit message on the command line, use 'git commit -m "MESSAGE"'. | |
+ You can stage and commit working files in one operation using command 'git commit | |
FILE ...', where the specified FILEs are modified tracked files. | |
+ You can stage and commit all modified tracked files in one operation using command | |
'git commit -a'. | |
+ Staging and committing in one operation is not advised. The preferred workflow is to | |
stage multiple changes over time, then commit once for a set of related staged | |
changes. | |
- Each commit contains the following data: | |
+ A unique 160-bit ID (a SHA-1 hash). The hash is displayed as 40 hex digits, but is | |
sometimes abbreviated to the leftmost 7 hex digits. | |
+ The SHA-1 hash of its "parent" commit, which is the commit chronologically preceding | |
it in the branch. This is how commits are chained in historical order. The one | |
exception is that the very first commit in a repo has no parent. | |
+ A short message from the author describing the commit. | |
+ All tracked files in the branch at the time of the commit. Unlike other revision | |
control systems, Git does not store deltas. This doesn't waste space, because Git | |
implements a reference-counted, content-addressable, compressed file store (see | |
https://tinyurl.com/gitobj). | |
+ An optional GPG digital signature by the author. | |
+ Miscellaneous metadata: commit time, author's name and email, etc. | |
People collaborate on a project by copying commits between their local repos and a common | |
remote repo. | |
- Copying commits from a local repo to a remote is a "push". | |
+ Use command 'git push' to push all commits in all branches to the remote repo. The | |
only commits pushed are those that do not yet exist in the remote. You can use | |
command-line options and arguments to restrict a push to just one branch. | |
+ A push is how you actually share your work. A commit to your local repo does not | |
share anything, because only you use your local repo. | |
- Copying commits from a remote to a local repo is a "pull" or "fetch". A pull is a | |
superset of a fetch (more on pull and fetch later). | |
- Here, four users (Joe, Sue, Pat, and Bob) each have their own local repos. They | |
collaborate by sharing a common remote. This is a hub-and-spoke topology, where the | |
remote is the hub and local repos are on the spokes: | |
Joe: WORKING FILES <-> INDEX <-> LOCAL REPO <---\ | |
Sue: WORKING FILES <-> INDEX <-> LOCAL REPO <----\ | |
+--> REMOTE REPO | |
Pat: WORKING FILES <-> INDEX <-> LOCAL REPO <----/ | |
Bob: WORKING FILES <-> INDEX <-> LOCAL REPO <---/ | |
- A remote is identified by an URL and a short name. | |
+ The hostname in the URL is the server that hosts the remote. Here are the URLs for | |
some interesting remote repos that you can clone: | |
https://github.com/torvalds/linux.git - The Linux kernel | |
https://github.com/dotnet/core.git - Microsoft's .NET Core | |
https://github.com/dotnet/roslyn.git - Microsoft's Visual Studio compiler | |
https://github.com/apple/swift.git - Apple's Swift programming language | |
https://github.com/golang/go.git - Google's Go programming language | |
https://github.com/chrislgarry/Apollo-11.git - Apollo 11 guidance computer source | |
+ The short name of a remote is a convenient name chosen by the owner of the local | |
repo. The scope of a short name is a local repo, so different people can use | |
the same short names in their repos without problem. | |
+ When you clone a remote repo, the default short name of the remote is "origin", but | |
this can be changed at any time. | |
A branch is a named time-ordered sequence of commits. Every commit except the first points to | |
one (or sometimes two) "parent" commits, forming a history tree of all branches. | |
- A branch name is simply a "reference" to the latest commit in the branch (more on | |
references later). This makes Git branches very lightweight. Here, branch "master" | |
references commit C7. It is the current branch, and the branch contains eight commits: | |
C0 <- C1 <- C2 <- C3 <- C4 <- C7 <- "master" (current branch) | |
- In these diagrams, arrows point to each commit's parent, forming the chronological | |
history of commits. C0 is the only commit with no parent, because it is the first | |
commit. | |
- You create a branch with command 'git branch BRANCHNAME'. This creates the named branch | |
so that it references the latest commit in the current branch, but it does not checkout | |
the new branch, so the current branch does not change. | |
- Example: If the current branch is "master", and the most recent commit was C7, then | |
command 'git branch mybranch' would result in this, where "mybranch" and "master" both | |
reference commit C7: | |
+- "mybranch" | |
V | |
C0 <- C1 <- C2 <- C3 <- C4 <- C7 <- "master" (current branch) | |
- If you then do 'git checkout mybranch' and make a new commit (C8), the new commit is part | |
of "mybranch" instead of "master": | |
+- C8 <- "mybranch" (current branch) | |
V | |
C0 <- C1 <- C2 <- C3 <- C4 <- C7 <- "master" | |
- If you then checkout the "master" branch and make a new commit (C9), the new commit goes | |
in the "master" branch: | |
+- C8 <- "mybranch" | |
V | |
C0 <- C1 <- C2 <- C3 <- C4 <- C7 <- C9 <- "master" (current branch) | |
- Above, branch "mybranch" and branch "master" diverge at commit C7, the common ancestor. | |
All branches share a common ancestor with some other branch. This means the commits in a | |
repo form a directed acyclic graph (DAG) rooted at the very first commit in the repo. | |
- A branch in your local repo becomes visible to other users when you push it (and the | |
commits it contains) to a remote. A push normally copies all local branches to the | |
remote, but you can restrict it to just one or some branches. | |
- A branch can be deleted with command 'git branch -d BRANCH', but that only deletes the | |
branch's name to reduce clutter. A commit contiues to exist as long as it is referenced | |
by a child commit, a branch name, or a "tag" (a very lightweight label that points to a | |
commit). | |
- Git garbage collects commits that have no references. In the below diagram, if you were | |
to delete branch "newfeature", the only reference to commit C52 would be removed, causing | |
C52 to be garbage collected. But then C51 is unreferenced, so it would also be garbage | |
collected. Beware: deleting a branch destroys commits! | |
+- C51 <- C52 <- "newfeature" | |
V | |
... <- C47 <- C48 <- C49 <- C50 <- "master" | |
- For safety, Git never garbage collects an object that's less than two weeks old. This | |
gives you time to change your mind and recover unreferenced commits. | |
A branch can be "merged" into any other branch. | |
- The result is a "merge commit" in the target branch. Here, branch "bugfix" has been | |
merged into branch "master", creating merge commit C8: | |
+- C5 <- C6 <-----+ <- "bugfix" | |
V | | |
C0 <- C1 <- C2 <- C3 <- C4 <- C7 <- C8 <- "master" | |
- A merge commit always has _two_ parent commits, one from each of the branches that were | |
merged. Above, the parents of merge commit C8 are commits C6 and C7. | |
- After a merge, both branches can continue to accumulate commits. Later, they can be | |
merged again. Here, a second merge has created merge commit C13, then commit C14 was | |
created on branch "master": | |
+- C5 <- C6 <-----+ <- C10 <- C11 <--+ <- "bugfix" | |
V | | | |
C0 <- C1 <- C2 <- C3 <- C4 <- C7 <- C8 <- C9 <- C12 <- C13 <- C14 <- "master" | |
- A merge may cause "merge conflicts" in files, which are places where the same lines were | |
changed in both branches. | |
+ Merge conflicts are marked with a special syntax around the conflicting lines: | |
Here are lines that are either unchanged from the common | |
ancestor, or cleanly resolved because only one side changed. | |
<<<<<<< yours:sample.txt | |
Conflict resolution is hard. | |
Let's go shopping. | |
======= | |
Git makes conflict resolution easy. | |
>>>>>>> theirs:sample.txt | |
And here is another line that is cleanly resolved or unmodified. | |
+ The area where a pair of conflicting changes happened is marked with '<<<<<<<', | |
'=======', and '>>>>>>>'. The part before the '=======' is typically your change, | |
and the part afterwards is typically someone else's change. | |
+ You can change the conflict marker style to show a 3-way diff (see section "HOW | |
CONFLICTS ARE PRESENTED" in the help displayed by 'git help merge'). In that case, a | |
conflict appears like this (note the new marker '|||||||'): | |
Here are lines that are either unchanged from the common | |
ancestor, or cleanly resolved because only one side changed. | |
<<<<<<< yours:sample.txt | |
Conflict resolution is hard. | |
Let's go shopping. | |
||||||| | |
This is the orignal text from the common ancestor of the conflicting changes. | |
======= | |
Git makes conflict resolution easy. | |
>>>>>>> theirs:sample.txt | |
And here is another line that is cleanly resolved or unmodified. | |
+ After fixing merge conflicts in a file (including removing those marker lines), you | |
"resolve" that file's conflicts by staging the file with 'git add FILE'. | |
+ You complete the merge by committing all of the staged merged files in a single | |
commit. This creates the merge commit. This is a use case where you MUST accumulate | |
changes (the resolved merge conflicts) in the index before making a single commit to | |
finish the merge. | |
- If you pull other people's commits from a remote branch, and you've made commits to your | |
local branch since your previous pull, then a "merge" will happen automatically, because | |
the history of your local branch has diverged from the history of the remote branch. | |
This is normal and unavoidable, due to Git's distributed nature. | |
- Pushes never cause merges, because you aren't allowed to push to a remote unless you were | |
the most recent person to pull from it. Thus, all merges happen in someone's local repo | |
and never in a remote. | |
The special reference "HEAD". | |
- The reference "HEAD" always points to the name of the current branch, so it's actually a | |
reference to a reference. This extra indirection means HEAD always references | |
(indirectly) the latest commit in the current branch, even as the branch name changes to | |
reference new commits in the branch. | |
- When you do a commit, the new commit is always added to the branch referenced by HEAD. | |
Here, commit C3 is added to branch "master", which is the current branch. Reference | |
"master" changes to point to C3, but reference "HEAD" continues to point to "master", | |
so it now (indirectly) references C3 instead of C2: | |
Before: C1 <- C2 <- master <- HEAD | |
After: C1 <- C2 <- C3 <- master <- HEAD | |
- Here is how HEAD changes when you switch from branch "master" to branch "newfeature" | |
using command 'git checkout newfeature': | |
Before: ... <- C10 <- C11 <- master <- HEAD | |
... <- C26 <- C27 <- newfeature | |
After: ... <- C10 <- C11 <- master | |
... <- C26 <- C27 <- newfeature <- HEAD | |
- To see which branch is current, use 'git status'. In this output, the current branch is | |
"master": | |
$ git status | |
On branch master | |
Your branch is up-to-date with 'origin/master'. | |
nothing to commit, working directory clean | |
- Above, note the mention to 'origin/master'. This notation connects the short name of a | |
remote ("origin") to the name of a branch ("master") with a '/' between them. This is | |
called a "remote tracking branch". More on these in the Advanced Concepts section. | |
Stashing. | |
- UNDER CONSTRUCTION | |
There are several kinds of branches. | |
- A "local branch" is a branch in your local repo. | |
- A "remote branch" is a branch in a remote repo. It exists for sharing commits with | |
others. People don't do day-to-day work in remote branches, so remote repos typically | |
have no working files. A repo without working files is called a "bare" repo. | |
- A "tracking branch" is a local branch that has an associated remote branch, called the | |
"upstream branch" or simply the "upstream". | |
+ When you push and pull, you synchronize tracking branches with their upstream | |
branches. Pushes send commits and references from a tracking branch to its upstream | |
branch. Pulls do the opposite. | |
+ You can set, clear, and change the upstream branch of a local branch at any time. | |
Don't go crazy. If you have a local branch containing the .NET source, and you set | |
its upstream to be a remote branch containing the Linux source, and then you do a | |
pull, Git will happily merge Linux into .NET. Oh, the humanity! | |
+ A local branch does not need an upstream branch. For instance, a "topic branch" is a | |
short-lived local branch used to isolate work (e.g., branch "bugfix" in the example | |
above). It needs no upstream branch, because eventually it will be merged into | |
another local branch. | |
- A "remote-tracking branch" is a read-only branch in your local repo that exactly matches | |
the state of a remote branch. This may seem like unnecessary duplication of state, but | |
remote tracking branches exist for a reason. More on these kinds of branches later in | |
the 'Advanced Concepts' section. | |
References. QUESTION: Should this section be moved up? | |
- References allow you to use human-readable names instead of SHA-1 hashes to refer to | |
commits. And since a branch is a chain of commits, references are also a way to refer to | |
branches. | |
- A "reference" is a symbolic name that points to a commit. A branch name is simply a | |
reference that points to the most recent commit in that branch. A "tag" is a reference | |
to an arbitrary commit to mark historic milestones. | |
- The command 'git show-ref' lists all references in your local repo: | |
$ git show-ref | |
fee6f1a6ae348935181ee6bfec59d1682bf6a22a refs/heads/master | |
fee6f1a6ae348935181ee6bfec59d1682bf6a22a refs/remotes/origin/HEAD | |
fee6f1a6ae348935181ee6bfec59d1682bf6a22a refs/remotes/origin/master | |
b4f7a8752c312e934bd122b2a3b5d1a81af93764 refs/tags/qa-release-1 | |
- Above, hex values are SHA-1 hashes of commits pointed to by the references on the right. | |
- Reference names resemble pathnames and have a hierarchical structure. | |
+ Local branches are under "refs/heads". | |
+ Tags are under "refs/tags". | |
+ Remote-tracking branches are under "refs/remotes". Here, "origin" is the short name | |
of a remote, and under it are references to remote-tracking branches "master" and | |
"HEAD". Read more about remote-tracking branches in the 'Advanced Concepts' section. | |
This is a typical Git workflow for collaborating with others: | |
- In your local repo, make a short-lived topic branch (e.g., "fixvan12345"), switch to it | |
using 'git checkout fixvan12345', and stage/commit some work leaving no modified working | |
files. | |
- Checkout tracking branch "master". Pull from the upstream branch to merge recent commits | |
from collaborators into your local repo. If there are merge conflicts, resolve and | |
commit them. | |
- Merge topic branch "fixvan12345" into tracking branch "master". If there are merge | |
conflicts, resolve and commit them. Delete topic branch "fixvan12345". | |
- Push tracking branch "master" to upstream branch "master" in the remote. If others have | |
pushed since your last pull, you will first need to pull again (and potetially resolve | |
merge conflicts). | |
- Your collaborators pull from the remote to merge your commits into their local "master" | |
branches. | |
- Rinse, repeat. | |
================================================================================ | |
Advanced Concepts | |
================================================================================ | |
Fetching and pulling. | |
- After your collaborators push their commits to a branch in the remote repo, you will want | |
to copy their commits into your local repo. You do this by performing a "fetch" from the | |
remote branch. | |
- The command 'git fetch' will fetch all commits that you do not yet have from all remote | |
branches. If new branches have been created in the remote, it fetches them too. | |
+ As a distributed revision control system, Git's goal is for your local repo to have | |
everything that's in the remote repo. | |
+ To fetch just one branch, use 'git fetch REMOTE BRANCH', where REMOTE is the short | |
name of the remote, and BRANCH is the name of the of the local and remote branch | |
(assuming they have the same name). | |
+ If the local and remote branch names differ, use 'git fetch REMOTE LBRANCH:RBRANCH', | |
where LBRANCH is the name of the local branch, and RBRANCH is the name of the remote | |
branch. | |
- A fetch retrieves new commits from the remote repo, including new branches and the | |
commits in them, but it does _NOT_ alter your local branches, index, or working files. | |
- You must do a "merge" before you can see the changes from fetched commits in your local | |
branches, index, and working files. Details about how this works are in the following | |
sections. | |
- The pair of operations fetch-then-merge is so common that the "pull" command does both in | |
one operation for convenience. The command 'git pull' is literally identical to 'git | |
fetch' followed immediately by 'git merge'. | |
The role of remote-tracking branches in fetching and merging. | |
- It's tempting to think that a pull merges upstream branches _directly_ into the | |
corresponding local branches, but the reality is more subtle, even if the effect is the | |
same. | |
+ Recall that a pull is a fetch followed by a merge. | |
+ Fetches are networked, because they communicate with a remote Git server. Merges are | |
always local and non-networked. You can do 'git fetch', disconnect from the network, | |
then do 'git merge', and it works. So where does the fetch put the fetched commits | |
so they are available to be merged later when there is no network? | |
+ A fetch makes a read-only copy in your local repo of each remote branch that contains | |
the fetched commits. This local read-only copy of a remote branch is called a | |
"remote-tracking branch". | |
+ A remote-tracking branch exists in your local repo. It is a local cache of the state | |
of a remote branch at the time of the last fetch. | |
+ So the answer to the above question is: Fetched commits are put into remote-tracking | |
branches, where they wait to be merged into your local branches. | |
- A remote-tracking branch has a name of the form REMOTE/BRANCH, such as "origin/master" or | |
"doc/update1". | |
+ REMOTE is the short name of a remote repo, and BRANCH is the name of a remote branch. | |
+ If your local branch names are the same as their upstream branches, then BRANCH will | |
also (coincidentally) be the name of the local tracking branch for the remote branch. | |
+ Be careful! It's easy to see the branch name "origin/bugfix42" and think "That's a | |
branch named 'bugfix42' in the remote repo named 'origin'", but not so. It's a | |
remote-tracking branch in your local repo named "origin/bugfix42". | |
- The purpose of a remote-tracking branch is to give you local read-only access to the | |
state of a remote branch, so you can examine it and merge commits from it. All you can | |
do with it is diff against it, merge from it, and update it by fetching the latest state | |
from the remote. | |
- A remote-tracking branch can be out-of-date if time has passed since the last fetch from | |
the remote. The next fetch makes it up-to-date again. | |
Example of fetching and merging: | |
- If your local branch "master" has an upstream branch in remote "origin", then you have a | |
local tracking branch named "master" and a remote-tracking branch named "origin/master": | |
+- "origin/master" | |
V | |
... <- C21 <- C22 <- C23 <- C24 <- C25 <- C26 <- "master" | |
Above, you've made two commits, C25 and C26, in local branch "master" that did not exist | |
in the upstream branch at the time of the most recent pull or fetch. | |
- Then you do a 'git fetch', and things change: | |
+- C27 <- C28 <- "origin/master" | |
V | |
... <- C21 <- C22 <- C23 <- C24 <- C25 <- C26 <- "master" | |
Now, commits C27 and C28 have been fetched from the remote, because one of your | |
collaborators pushed them to the remote's "master" branch. Remote-tracking branch | |
"origin/master" has been updated to reference commit C28. | |
- Then you merge with 'git merge', and you now have a new merge commit (C29): | |
+- C27 <- C28 <------+ <- "origin/master" | |
V | | |
... <- C21 <- C22 <- C23 <- C24 <- C25 <- C26 <- C29 <- "master" | |
- Now, a 'git push' will push commits C25, C26, and C29 to the remote, for others to fetch | |
for themselves. Other collaborators will need to merge if they have their own local | |
commits parented to C28, just as you needed to merge above. | |
- It seems coincidental that every remote-tracking branch connects to your local repo's | |
commit graph at some common ancestor commit in one of your branches. Why is this always | |
the case? | |
+ Every collaborator's local repo contains a directed acyclic graph (DAG) of commits | |
rooted at the same initial commit: C0, the first commit in the first local repo where | |
the project started. | |
+ Git maintains a shared consensus among all contributors about the contents and shape | |
of the commit graph. Some contributors may not see the most recent commits if they | |
haven't fetched in a while, but if all contributors were to pull, they would all have | |
the same commit graph (i.e., every commit in every branch). | |
GitHub adds another level of indirection. It connects remote repos to each other. | |
- GitHub users can "fork" someone else's remote repo (hosted on GitHub) to create their own | |
personal copy of the remote. This copy is also a remote repo. Here, the four remotes on | |
the left are "forked" from the remote on the right: | |
LOCAL REPO(s) <-> REMOTE REPO <---\ | |
LOCAL REPO(s) <-> REMOTE REPO <----\ | |
+-- REMOTE REPO <-> LOCAL REPO(s) | |
LOCAL REPO(s) <-> REMOTE REPO <----/ | |
LOCAL REPO(s) <-> REMOTE REPO <---/ | |
- This is how the Linux kernel is developed and how Microsoft accepts contributions to | |
.NET. The remote on the right is the official repo and is writable only by its | |
maintainers. The remotes on the left belong to contributors. | |
- At the time this document was written, Linux has over 11,000 forks, and .NET has almost | |
2000 forks. The forked remote repos are also hosted by GitHub, so the contributors don't | |
need to run their own Git servers. | |
- When a contributor produces a commit of value, he pushes it to his personal remote and | |
submits a GitHub "pull request" to the maintainers asking them to evaluate the commit. | |
The maintainers can choose to pull the commit into the official repo. | |
- Keep in mind that "forking" and "pull requests" are not part of Git. GitHub invented | |
these things as part of their added layer of functionality. | |
- GitHub is owned by Microsoft. So Microsoft operates the source control system for the | |
Linux kernel. | |
Undoing changes to working files. | |
- WARNING: The Git commands to undo changes can delete data permanently. The deleted data | |
is lost unless you have it backed up. | |
- Suppose you accidentally edit the wrong working file or you modify a working file and | |
later decide you didn't want to change it. To undo changes to a modified working file do | |
this: | |
git checkout FILE | |
- The above command reverts a working file so it's identical to the copy in the index. | |
This will destroy your changes, so be careful! | |
- Note that 'git checkout FILE' overwrites your modifications to FILE, but if you use 'git | |
checkout BRANCH' to switch to a different branch, your modified working files are NOT | |
overwritten. | |
- In other revision control systems a "checkout" operation is typically non-destructive. | |
In Git, a checkout sometimes overwrites your changes to a working file! For Perforce | |
users, 'git checkout FILE' is the same as reverting a checked out file, or if the file | |
was modified but not checked out, it's the same as a "forced get latest". | |
Undoing changes to the index and local repo. | |
- Suppose you've done 'git add FILE' or 'git commit FILE', which change the index and local | |
repo (respectively). Those operations can be undone using Git's 'reset' command. See | |
https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified for nice graphics to help | |
understand this section. | |
- There are three types of reset: soft, mixed, and hard. Soft makes the fewest changes. | |
Mixed makes more changes than soft. Hard makes the most changes. | |
+ Recall where files reside in a local repo: | |
WORKING FILES <-> INDEX <-> LOCAL REPO | |
+ A SOFT reset changes only the local repo. | |
+ A MIXED reset changes the local repo and the index, but not the working files. | |
+ A HARD reset changes the local repo, the index, and the working files. This kind of | |
reset is dangerous, because it can delete and overwrite working files. | |
+ Graphically: | |
+------------+-----------+------ HARD reset changes all three. | |
| | | | |
| +-----------+------ MIXED reset changes these two. | |
| | | | |
| | +------ SOFT reset changes just this. | |
| | | | |
V V V | |
WORKING FILES <-> INDEX <-> LOCAL REPO | |
- The "git reset" command takes an existing COMMIT as an argument, and changes the current | |
branch to reference that commit. It moves a branch reference so that it points to a | |
different commit. Let's see what that looks like. | |
+ The specified COMMIT is usually an ancestor of the most recent commit in the branch, | |
so the effect is to undo all commits in the branch that follow COMMIT. | |
+ The COMMIT can be identified by a SHA-1 hash (or its first few digits), a branch name | |
that references the commit, a tag name that references the commit, or one of the | |
ancestry reference syntaxes supported by Git. | |
+ Suppose branch "master" has these commits: | |
... <- C21 <- C22 <- C23 <- C24 <- C25 <- C26 <- "master" | |
+ Suppose the SHA-1 hash of C24 is f13a7d9ac039e5f6c6eedbb5dad9faf42c82e659. The | |
command 'git reset --soft f13da7d' (note the '--soft' switch) will change the commit | |
graph to look like this: | |
+- C25 <- C26 | |
V | |
... <- C21 <- C22 <- C23 <- C24 <- "master" | |
+ Commits C25 and C26 are now deleted from branch "master", which is now a reference to | |
C24. The deleted commits will continue to dangle off the commit graph for a couple | |
of weeks, and then they'll be garbage collected. | |
+ If you decide you want to un-delete commit C25 before it's garbage collected, just do | |
'git reset --soft C25HASH', where C25HASH is the SHA-1 hash of commit C25. The | |
commit graph will change to this: | |
+- C26 | |
V | |
... <- C21 <- C22 <- C23 <- C24 <- C25 <- "master" | |
+ Thus, the reset command can both undo commits and restore deleted commits (as long as | |
they haven't been garbage collected). | |
- The example above uses the --soft switch, so the change only affects the local repo not | |
the index or working files. | |
+ After you delete commits with a soft reset, the changes in those commits remain in | |
the index and in your working files. Your index and working files are "out-of-date" | |
with respect to the local repo, because they have data that has since been "undone" | |
in the local repo. | |
+ Why do a soft reset? A common reason is that you committed some code that doesn't | |
work correctly or just isn't ready to be shared with your collaborators yet. After | |
doing the soft reset, you can do a push to share the reset with collaborators. If | |
the undone commits where never pushed, then you don't need to push anything. | |
+ UNDER CONSTRUCTION: Warn about using reset to delete commits that have already been | |
pushed. | |
- If you want to delete commits from the local repo _and_ unstage the changed files from | |
the index, do 'git reset --mixed COMMITHASH'. Mixed resets are the default, so you can | |
omit the --mixed switch. | |
+ After a mixed reset, the changes to the files in the deleted commits exist only in | |
your working files (and for a couple of weeks in the local repo, until garbage | |
collected). The files in the index exactly match the commit at the tip of the | |
branch. | |
+ A mixed reset is the default, because when most people undo a commit they typically | |
also want to un-stage the associated files, leaving them with only the modified | |
working files. This is like travelling back in time to a point before the changes | |
were staged. | |
- Soft and mixed resets are useful when you change your mind about making a commit. | |
However, a hard reset is all that and more. It's the most dangerous form of reset. | |
+ UNDER CONSTRUCTION | |
- Here's a quick summary soft, mixed, and hard resets: | |
Type of reset Effect of command 'git reset --TYPE COMMIT' | |
------------- --------------------------------------------------------------------- | |
soft 1. Changes the current branch in the local repo to reference COMMIT. | |
RESULT: This deletes commits after or restores commits before COMMIT, | |
depending on the direction of the reset. | |
mixed 1. Changes the current branch in the local repo to reference COMMIT. | |
2. Changes the files from COMMIT in the index to match the current | |
branch in the local repo. | |
RESULT: Same as soft but also unstages related files from the deleted | |
commits. | |
hard 1. Changes the current branch in the local repo to reference COMMIT. | |
2. Changes the files from COMMIT in the index to match the current | |
branch in the local repo. | |
3. Changes the files from COMMIT in the working files to match the | |
index and local repo. WARNING: This overwrites working files! | |
RESULT: Same as mixed, but also overwrites related working files. | |
- The reset command works differently if a file is specified. | |
+ When a file is given, the "soft" step is skipped, because you can't move a branch | |
reference for just one file. So only the "mixed" and "hard" steps are available. | |
+ To revert a modified working file _and_ the staged copy of the file to be identical | |
to the copy in the local repo, do: | |
git reset --hard FILE | |
This is more dangerous than 'git checkout FILE', because you may have days or weeks | |
of work on that file staged in your index, and it is all lost. | |
- It's important to remember that a reset can only affect the local repo, the index, and | |
working files, depending on which kind of reset you do. After you push your commits to a | |
remote repo, a reset cannot help you, because a reset cannot un-push commits! | |
- So what do you do if you have pushed some commits that you want to undo? You need to | |
revert your commits. | |
Reverting commits. | |
- UNDER CONSTRUCTION | |
- git revert ... | |
- Git HowTo: revert a commit already pushed to a remote repository: | |
http://christoph.ruegg.name/blog/git-howto-revert-a-commit-already-pushed-to-a-remote-reposit.html | |
Squashing. | |
- See https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified#Squashing for how to use | |
"git reset --soft" for squashing commits. | |
- UNDER CONSTRUCTION | |
Rebasing. | |
- UNDER CONSTRUCTION | |
Plumbing and porcelain. | |
- UNDER CONSTRUCTION | |
================================================================================ | |
Git Command Quick Reference | |
================================================================================ | |
These entries are ordered roughly in the order you need to use the commands when setting up Git | |
and starting work on a new repository. | |
Configuration commands: | |
git config [ --local | --global | --system ] OPTION VALUE | |
Sets configuration OPTION to VALUE. With --local, the option is written to the local | |
repo's .git/config file, and they only apply to that repo. With --global, the option | |
is written to the user's personal ~/.gitconfig file. With --system, the option is | |
written to the system-wide Git config file (e.g., /etc/gitconfig). System options | |
apply to all users and all repos on the machine. Global options apply to all repos | |
used by a given user, and they override system options. Local options apply to just | |
one repo, and they override global and system options. The default is --local. | |
Type "git help config" for a list of configuration options. It is recommended to at | |
least set these global options before using Git: | |
git config --global user.name "Joe Smith" | |
git config --global user.email "[email protected]" | |
git config --global core.editor vim | |
git config --list [ --local | --global | --system ] | |
Shows the current configuration options that apply to the current repo and user. With | |
--local, --global, or --system, this show only the specified options. | |
git config [ --local | --global | --system ] --unset OPTION | |
Removes the given option. | |
Command aliases: | |
git config [ --local | --global | --system ] alias.last "log -1 HEAD" | |
git config [ --local | --global | --system ] alias.logbranches "log --oneline --decorate --graph --all" | |
git config [ --local | --global | --system ] alias.unstage "reset HEAD" | |
Defines command aliases. | |
References: | |
HEAD always points to the currently checked out branch. | |
HEAD^ references the previous commit on the current branch. | |
HEAD~N references the Nth most recent commit on the current branch. | |
Thus, HEAD~1 is the same as HEAD^. | |
Create a new empty local repo: | |
- Make a new directory, cd into it, then type 'git init'. | |
git init | |
After this, use 'git add ...' to add files or 'git remote add ...' to add a remote repo | |
from which you can pull commits. This is not needed if you clone a remote repo. | |
Clone a remote repository: | |
git clone REPO-URL | |
Creates a local repo in the current directory cloned from the remote repo identified by | |
REPO-URL. Give an HTTPS-style URL if you need read-only access to the remote repo. | |
Give a GIT-style or SSH-style URL if you plan to push to the remote repo. See | |
https://tinyurl.com/githubssh for how to configure SSH for access to a remote repo. | |
This automatically creates a remote-tracking brach for origin/master. | |
TODO: Show HTTPS and SSH URL syntax. | |
Status of the local repo: | |
git status [ -s ] | |
Shows status of modified working files and staged files. Also shows if the local repo | |
is ahead or behind the remote repo in terms of commits. With -s, shows short status | |
where column 1 represents staged files, and column 2 represents working files. | |
Add files to the local repo: | |
git add FILE-OR-DIR ... | |
Begins tracking the given files, stages modified working files, or marks a merge | |
conflict as resolved in the given files. If a directory is given, all the files in it | |
are added (recursively including all subdirectories). If FILE-OR-DIR is a symbolic | |
link, the symlink itself is added not what it points to. | |
Remove files from the local repo: | |
git rm [ --cached ] FILE ... | |
Stages deletion of FILEs. After this, you must commit to remove it from the repo. | |
This removes FILE from the working and staged files. Option --cached leaves the files | |
in the working files. | |
Rename a file: | |
QUESTION: How is a directory renamed? | |
git mv OLDFILE NEWFILE | |
Syntactic sugar for: git rm --cached OLDFILE; mv OLDFILE NEWFILE; git add NEWFILE | |
Stage/unstage modified working files: | |
git add FILE ... | |
Stages modified tracked FILEs. Must later commit to get the changes into the local | |
repo. | |
QUESTION: Do these reset commands affect the local repo or just staged files? Maybe move | |
these to the 'Undoing changes' section below. | |
git reset HEAD [ FILE ... ] | |
git reset --mixed HEAD [ FILE ... ] | |
Unstages FILEs (or all files if FILE is omitted) by making the index match the local | |
repo for this file. Does not modify or delete any working files. | |
Differences: | |
NOTE: See the gitrevisions man page (or type "git help revisions") for the syntax for | |
specifying revisions and ranges. | |
TODO: Maybe integrate info from https://raw.githubusercontent.com/Osse/git-stuff/master/dots.txt | |
here. | |
git show COMMIT | |
Show the diff for COMMIT. | |
git diff | |
Compares working files with staged files. | |
git diff HEAD | |
Compares working files with the latest commit (HEAD) in the local repo. | |
git diff --staged | |
Compares the staged files with the latest commit. | |
git diff --stat | |
Show a summary of changes instead of the modified lines. | |
git diff <options> -- FILE | |
Same as above commands but limit output to FILE. | |
git diff COMMIT | |
Compares working files with COMMIT in the local repo. | |
git diff COMMIT1 COMMIT2 | |
Compares COMMIT1 with COMMIT2 in the local repo. | |
git diff COMMIT1..COMMIT2 | |
Same as previous. If <commit> on one side is omitted, it defaults to HEAD. | |
git diff HEAD^ HEAD | |
Compares the commit before the most recent commit with with the most recent commit in | |
the local repo. | |
git diff BRANCH1..BRANCH2 | |
Compares the tips of BRANCH1 and BRANCH2. Not very useful. Typically, you want the | |
X...Y form (below). | |
git diff BRANCH..REMOTE/BRANCH | |
Compares local BRANCH with REMOTE/BRANCH. | |
git diff BRANCH1...BRANCH2 | |
Compares BRANCH2 to the common ancestor of BRANCH2 and BRANCH1. | |
Commit changes to the local repo: | |
git commit [ -m MSG ] | |
Commits all staged files. Does not stage or commit any working files. Launches an | |
editor if -m not given. | |
git commit [ -m MSG ] FILE ... | |
Stages and commits the given working files. Launches an editor if -m not given. This | |
can leave the index out-of-sync with the local repo and working files. | |
git commit -a [ -m MSG ] | |
Stages and commits all modified working files. No files can be specified with -a. | |
Launches an editor if -m not given. | |
git commit --amend | |
Undoes the last commit, puts the working files back as they were with the changes | |
staged and the commit message ready to edit next time you commit. IMPORTANT: Do NOT | |
ammend the last commit if it has already been pushed to a remote repo, because this | |
changes the SHA-1 hash of the last commit. | |
View the commit log: | |
git log | |
Show all commits to the local repo. | |
git log -p | |
Show all commits to the local repo with diffs for each change. | |
git log BRANCH | |
Show all commits in BRANCH. | |
git log BRANCH1 ^BRANCH2 | |
Show all commits in BRANCH1 that are not in BRANCH2. | |
git log REMOTE/BRANCH..HEAD | |
Show all commits to the local repo that have not yet been pushed to REMOTE/BRANCH. | |
git log --author=Andy | |
Show commits where the author name contains "Andy". | |
git log --grep=REGEX | |
Show commits where the commit message matches REGEX. | |
git log -G REGEX | |
Show commits where the diff contains text that matches REGEX. | |
git log --since=2.months.ago --until=1.day.ago | |
Show commits by date range. | |
git log --since=2.months.ago --until=1.day.ago --author=Andy -G "something" --all-match | |
Mix and match. Use --all-match to AND the options (default is OR). | |
git blame FILE | |
Show who modified each line of FILE at what time along with the commit hash. | |
Revert changes: | |
git reset --soft COMMIT | |
COMMIT defaults to HEAD. Omitting COMMIT does nothing, because the branch name is | |
already what HEAD references. It's the same as "git reset --soft HEAD", which is a | |
no-op. | |
git reset COMMIT | |
git reset --mixed COMMIT | |
COMMIT defaults to HEAD. Also, --mixed is the default operation. | |
git reset --hard COMMIT | |
COMMIT defaults to HEAD. This unstages all staged bug not-yet-committed files and | |
overwrites all working file to match the index and the branch in the local repo. | |
git reset --mixed COMMIT FILE ... | |
Unstages FILE, leaving the copy in the index identical to the branch in the local repo. | |
git reset --hard COMMIT FILE ... | |
Unstages FILE and makes the working copy match the index and local repo, destroying | |
your local edits! | |
Delete untracked and/or ignored files: | |
git clean [ -d ] | |
Remove untracked files that are not ignored. With option -d, remove any directories | |
that become empty as a result of deleting files. | |
git clean -x | |
Also remove ignored files in addition to untracked files. This is useful for removing | |
build products (executables, libraries, etc.). | |
git clean -n ... | |
Show what would be removed without removing anything. | |
Stash working/staged files: | |
git stash [ --include-untracked | --all ] | |
Stashes all modified working files and staged files. Do this before switching between | |
branches to avoid losing work. Option --include-untracked means also stash untracked | |
files. Option --all means also stash untracked and ignored files. | |
git stash --keep-index | |
Stashes all modified working files but NOT staged files. | |
git stash list | |
Lists stashes, showing which commit was current for each. | |
git stash apply | |
Restores working files from the most recent stash (merging with working files if | |
necessary). This does NOT restore staged files. This does NOT pop the most recent | |
stash off the stack. | |
git stash apply --index | |
Restores working and staged files from the most recent stash (merging with working | |
files if necessary. This restores staged files too. This does NOT pop the most recent | |
stash off the stack. | |
git stash pop | |
Restores working files from the most recent stash (merging with working files if | |
necessary). This does NOT restore staged files. This pops the most recent stash off | |
the stack. | |
git stash pop --index | |
Restores working and staged files from the most recent stash (merging with working | |
files if necessary. This restores staged files too. This pops the most recent stash | |
off the stack. | |
git stash drop stash@{0} | |
Drops stash@{0} from the stash. | |
git stash branch NEWBRANCH | |
Creates a branch, checks out the commit where the most recent stash was made, applies | |
the stash to the branch, and drops the stash (if the stash was applied to the branch | |
cleanly). | |
View remote repo(s): | |
git remote [ -v ] | |
Show currently configured remote repos for this repo. Option -v shows the remote repo | |
URL. | |
git remote show REMOTE | |
Show event more info about REMOTE, including the remote's HEAD branch, fetch/push URLs | |
and which local branches track remote branches. | |
Add/remove a remote repo to/from the local repo: | |
- Having multiple remote repos associated with one local repo simply means your local repo | |
can have tracking branches for remote branches in different remote repos. In each of | |
these tracking branches, you can push/pull from any of the remote branches. Example: One | |
remote repo might be the main project repo on Github or a corporate server. Other remote | |
repos might be coworkers' clones of the main project. | |
- QUESTION: How is the default remote chosen for commands? How is the default switched? | |
git remote add [ SHORTNAME ] CLONEURL | |
Link local repo to remote repo. QUESTION: Is this necessary after "git clone ..."? It | |
doesn't seem to be. Maybe only after "git init"? | |
git remote rm REMOTE | |
Removes the remote repo. All remote-tracking branches and configuration settings for | |
the remote are removed. | |
git remote rename OLDREMOTE NEWREMOTE | |
Renames the remote repo. QUESTION: What exactly does this do and why would you do it? | |
Is this purely a local change? | |
Pull commits from a remote repo: | |
git fetch [ --dry-run ] [ REMOTE ] [ BRANCH ] | |
Fetch the current (or specified) branch from the current (or specified) remote repo | |
into the local repo. Working files are not changed. You need to do 'git merge ...' | |
to update working files after fetching, then 'git commit ...' to commit the results of | |
the merge. With --dry-run, show what would be done without doing it. QUESTION: Does | |
this update staged files? | |
git pull [ REMOTE ] [ BRANCH ] | |
Fetch, merge, and commit the current (or specified) branch from the current (or | |
specified) remote repo. If BRANCH is given, pull from that BRANCH instead of the | |
current HEAD. QUESTION: What happens if the specified BRANCH is not the current | |
branch? | |
Push commits to a remote repo: | |
git push [ REMOTE ] [ BRANCH ] | |
Pushes the current (or specified) branch to the current (or specified) remote repo from | |
the local repo. If another user has pushed since your last push, you are told to first | |
pull from the current remote repo and resolve any merge conflicts. | |
git push REMOTE BRANCH | |
Pushes BRANCH to repo REMOTE. | |
Create a branch: | |
git branch BRANCH | |
Creates BRANCH in the local repo with BRANCH referencing the commit referenced by HEAD. | |
git checkout -b BRANCH | |
Creates BRANCH in the local repo and checks it out. | |
git checkout -b BRANCH REMOTE/BRANCH | |
git checkout --track REMOTE/BRANCH | |
Creates BRANCH in the local repo based on the current local state of remote-tracking | |
branch REMOTE/BRANCH. The local branch is called a "tracking branch", because it | |
tracks a remote branch. You push and pull commits between the local branch and the | |
remote branch. | |
View branches: | |
git branch | |
Show branches in the local repo. Only fetched branches are shown. | |
git branch -r | |
Show all remote branches. | |
git branch -a | |
Show all branches (local and remote). | |
git branch -v | |
Show branches in the local repo with latest commit in each branch. | |
git branch -vv | |
Same as previous but also shows name of upstream branch (if there is one). | |
Switch working files between branches: | |
git checkout BRANCH | |
Check out local repo's BRANCH (e.g. "master"). This is how you switch working files | |
between branches. You may be told to "stash" your uncommitted modified working and | |
staged files before doing this. | |
Rename a local branch: | |
git branch -m OLDBRANCH NEWBRANCH | |
Renames a branch in the local repo. This is equivalent to creating a new branch that | |
is a copy of the old branch and deleting the old branch, like this: | |
git checkout -b NEWBRANCH OLDBRANCH // Copy old branch to new branch. | |
git branch -d OLDBRANCH // Delete old branch. | |
Delete a branch: | |
git branch -d BRANCH | |
Deletes BRANCH from the local repo. | |
git push REMOTE --delete BRANCH | |
git push REMOTE :BRANCH | |
Deletes BRANCH from the remote repo. | |
git remote prune | |
Deletes local branches that no longer exist on the remote repo. QUESTION: What is one | |
of the deleted branches is the current branch? | |
Merge a branch into another branch: | |
o Merging is completely local. If your remote-tracking branches are out-of-date, a merge | |
will not fetch up-to-date state. You need to do fetch from the remote branch to stay | |
up-to-data. A pull will do a fetch-and-merge. | |
- To do a merge, first checkout the destination branch using 'git checkout DESTBRANCH'. | |
Then use Git's 'merge' command to merge from the source branch (see below). | |
- If there are merge conflicts, resolve them manually, then do 'git add FILE ...' to mark | |
the conficted files as resolved. Then commit the resolved files eventually. | |
git merge [ --no-commit ] SRCBRANCH | |
Merge SRCBRANCH into HEAD. Unless --no-commit is given, this commits the result of the | |
merge to the local repo if there were no conflicts. | |
git merge --squash SRCBRANCH | |
Produce the working and staged file state as if a real merge happened (except for the | |
merge information), but do not actually make a commit. This allows you to create a | |
single commit to the current branch whose effect is the same as merging another branch. | |
git add FILE | |
Marks a merge conflict in FILE as resolved. You do this after manually resolving the | |
conflict by editting FILE. You need to commit the conflict fix after this. | |
Emacs hacks -- please ignore ... | |
Local variables: | |
fill-column: 95 | |
indent-tabs-mode: nil | |
paragraph-separate: "[ ]*$\\| git .*$" | |
paragraph-start: "[ ]*$\\| git .*$\\| +[-+*] $" | |
eval: (my-n-column-tabs 4) | |
eval: (auto-fill-mode 0) | |
End: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment