Synchronization โ
remote
: a git repository can have one or more remotes targeting to a uri(which means you can even add another local repository as remote with its path) exists in a git host.git remote add <remote_name> <uri>
.- each branch also has a upstream to track with remote just like the repository.
git fetch [<remote_name>]
: fetch all remote commits to local but do nothing, it only fetches and store it atrefs/remotes/<remote_name>/*
- use
git merge <remote_name>/<branch_name>
if you're ready to merge remote commits to local.
- use
pull
: fetch remote commits for current branch and merge them into current branch.- this requires the branch has a upstream set.
push
: synchronize branch to remote at git host
Remote โ
Remotes are implicit commits from the remote repository that can live optionally in your local repository. Each remote has its branches, which means each of its branch has a head commit stored in your local repository.
Remote Inspection โ
$ git remote -v # inspect all remotes
origin git@github.com:sharpchen/nixpkgs (fetch)
origin git@github.com:sharpchen/nixpkgs (push)
upstream git@github.com:NixOS/nixpkgs (fetch)
upstream git@github.com:NixOS/nixpkgs (push)
$ git branch -v -r # inspect all remote branches
2
3
4
5
6
7
Remote Naming Convention โ
The following convention is widely adopted by most git hosts such as github and gitlab, git host would add such remotes by convention when you fork one repository from another.
origin
: the remote represents the direct copy in a git host is usually named as origin- one repository can have one or more mirrors hosted on different git hosts, the most official one should be origin
git clone
would implicitly name remote to origin
upstream
: if current repository is a fork of another, the one been forked should be named asupstream
.
Remote Identifier โ
- full uri: such as
git@github.com:NixOS/nixpkgs
- remote name: such as
origin
Remote Branch Identifier โ
<remote_name>/<branch_name>
<branch_name>@{upstream}
or<branch_name>@{u}
: attached remote branch of<branch_name>
on local.@{upstream}
or@{u}
: attached remote branch of current branch(if you're on a branch)
Fetch โ
Merge โ
Pull โ
git pull <remote_name> <branch_name>
git branch -u <remote_name>/<branch_name> [<local_branch>] # make sure you have one upstream attached to the branch
git pull # pull remote commit from the attached upstream to current branch
2
Rebase on Pull โ
Rebasing on pull git pull --rebase
follows such steps behind the scene:
git fetch <current_branch>
: fetch remote commits of current branch- Git checkout to the remote branch and remove the new local commits, and replay the new local commits to on the base of remote.
- oops, conflict might happen at this point.
- git enters a pending stage to let you resolve the conflicts.
git rebase --continue
to apply the resolved changes when you're ready.- or
git rebase --abort
when you like to give up the rebasing, git reattach new local commits to local branch.
- this is effectively the same as moving new local commits to the top of the coming remote commits.
- oops, conflict might happen at this point.
- Git attaches the tail of coming remote commits to the top of old local commits, rebasing finished.
NOTE
replay refers to performing all actions to generate the same new local commits on the new base. Each stage of rebasing would be added to reflog.
NOTE
It's worth noting that rebasing shows a reversed side of conflicts that, HEAD
is coming from remote while the another side is coming from local. That's simply because the point when conflict happens, the recipient branch is the remote and the coming commits(we can't say it's a branch since it has no base at that point) are from local.
<<<<<<< HEAD
Code from the remote (what you're rebasing *onto*)
=======
...Your local patch being replayed
>>>>>>> (your commit being applied)
2
3
4
5
Git generates a merge commit directly with coming commits as the default behavior, while it's recommended to use git pull --rebase
to move your local divergence point that compared to the remote branch to the head of the coming commits. Rebasing on pull keeps the history in a intuitive order since changes from local are not pushed yet which should naturally behind the remote.
[pull]
rebase = true
2