Terminology convention: working tree –> stage –> local repo –> remote repo
git fetch —— Download objects and refs from another repository
git fetch fetches branches and/or tags (collectively, refs) from one or more other repositories, along with the objects necessary to complete their histories. Remote-tracking branches are updated.
When no remote is specified, by default the
origin remote will be used, unless there’s an upstream branch configured for the current branch.
The names of refs that are fetched, together with the object names they point at, are written to
.git/FETCH_HEAD.This information may be used by scripts or other git commands, such as
FETCH_HEAD is just a reference to the tip of the last fetch, whether that fetch was initiated directly using the fetch command or as part of a pull.
When we have the
branch.<name>.fetch set as:
This configuration is used in two ways:
The above command copies all branches from the remote
refs/heads/ namespace and stores them to the local
refs/remotes/origin/ namespace, unless the
branch.<name>.fetch option is used to specify a non-default refspec.
This command will fetch only the master branch. The
remote.<repository>.fetch values determine which remote-tracking branch, if any, is updated.
git merge —— Join two or more development histories together
git merge incorporates changes from the named commits (since the time their histories diverged from the current branch) into the current branch.
Assume the following history exists and the current branch is “master”:
A---B---C topic / D---E---F---G master
git merge topic will replay the changes made on the topic branch since it diverged from master (E) until its current commit (C) on top of master, and record the result in a new commit (H) along with the names of the two parent commits and a log message from the user describing the changes.
A---B---C topic / \ D---E---F---G---H master
Before performing any merge, we should make sure our codes are in good shape and commit all local changes.
git pull and
git merge will stop without doing anything when local uncommitted changes overlap with files that
git merge may need to update.
To avoid recording unrelated changes in the merge commit,
git pull and
git merge will also abort if there are any changes registered in the index relative to the
HEAD commit. (One exception is when the changed index entries are in the state that would result from the merge already.)
If all named commits are already ancestors of
git merge will exit early with the message “Already up-to-date.”
Often the current branch head is an ancestor of the named commit. This is the most common case especially when invoked from
git pull: we are tracking an upstream repository, we have committed no local changes, and now we want to update to a newer upstream revision. In this case, a new commit is not needed to store the combined history; instead, the
HEAD (along with the index) is updated to point at the named commit, without creating an extra merge commit.
This behavior can be suppressed with the
Except in a fast-forward merge (see above), the branches to be merged must be tied together by a merge commit that has both of them as its parents.
A merged version reconciling the changes from all branches to be merged is committed, and our
HEAD, index, and working tree are updated to it. It is possible to have modifications in the working tree as long as they do not overlap; the update will preserve them.
When it is not obvious how to reconcile the changes, the following happens:
HEADpointer stays the same.
MERGE_HEADref is set to point to the other branch head.
Paths that merged cleanly are updated both in the index file and in our working tree.
For conflicting paths, the index file records up to three versions: stage 1 stores the version from the common ancestor, stage 2 from
HEAD, and stage 3 from
MERGE_HEAD(we can inspect the stages with
git ls-files -u). The working tree files contain the result of the “merge” program; i.e. 3-way merge results with familiar conflict markers
No other changes are made. In particular, the local modifications we had before we started merge will stay the same and the index entries for them stay as they were, i.e. matching
If we tried a merge which resulted in complex conflicts and want to start over, we can recover with
git merge --abort.
After seeing a conflict, we can do two things:
Decide not to merge. The only clean-ups we need are to reset the index file to the
HEADcommit to reverse 2. and to clean up working tree changes made by 2. and 3.;
git merge --abortcan be used for this.
Resolve the conflicts. Git will mark the conflicts in the working tree. Edit the files into shape and git add them to the index. Use
git committo seal the deal.
git pull —— Fetch from and integrate with another repository or a local branch
git pull incorporates changes from a remote repository into the current branch. In its default mode,
git pull is shorthand for
git fetch followed by
git merge FETCH_HEAD.
git pull runs
git fetch with the given parameters and calls git merge to merge the retrieved branch heads into the current branch. See the More about config variables for more details.
Update the remote-tracking branches for the repository we cloned from, then merge one of them into our current branch:1git pull, git pull origin
Normally the branch merged in is the
HEADof the remote repository, but the choice is determined by the
To merge a specific remote branch
nextinto our current branch, we can run:1git pull origin next
This leaves a copy of next temporarily in
FETCH_HEAD, but does not update any remote-tracking branches. Using remote-tracking branches, the same can be done by invoking fetch and merge:12git fetch origingit merge origin/next
If we tried a pull which resulted in complex conflicts and would want to start over, we can recover with
Follow this stackoverflow answer to change the author name/email for a specific commit.
branch <name>, it tells git fetch and git push which remote to fetch from/push to.
Defines, together with
branch.<name>.remote, the upstream branch for the given branch. It tells git fetch/git pull/git rebase which branch to merge and can also affect git push (see push.default). When in
branch <name>, it tells git fetch the default refspec to be marked for merging in
branch <name>, it overrides
branch.<name>.remotefor pushing. It also overrides
remote.pushDefaultfor pushing from
branch <name>. When we pull from one place (e.g. our upstream) and push to another place (e.g. our own publishing repository), we would want to set
remote.pushDefaultto specify the remote to push to for all branches, and use this option to override it for a specific branch.
The remote to push to by default. Overrides
branch.<name>.remotefor all branches, and is overridden by
branch.<name>.pushRemotefor specific branches.
Disclaimer: This is my personal notes for Git reference. Some of the notes come from my daily experience and some come from other existing Git tutorials or documentations.