Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to understand remote "origin" fetch setting in .git/conf file?

I saw the command in .git/config when I learn pull & request from this article.

fetch = +refs/pull/*/head:refs/pull/origin/*

I open my config file which is different as this fetch = +refs/heads/*:refs/remotes/origin/*.

After I modify fetch setting line as the article read and run those git commands:

git fetch origin
git checkout -b 1 pull/origin/1

The config file automatic append this:

[branch "1"]
        remote = origin
        merge = refs/pull/1/head

Could someone can explain the means and difference settings of the fetch = ...?
Why [branch "1"] will be auto appended?

Thanks

like image 526
LoranceChen Avatar asked Dec 14 '17 13:12

LoranceChen


1 Answers

There's quite a lot to unpack here. Let's start from the beginning.

The Refspec

The value of the fetch setting is what's called a refspec, a special Git syntax used to map local branch references with remote ones.

It takes the form:

<source>:<destination>

In the case of fetch, <source> is a branch that exists on a remote repository, while <destination> is the branch it should map to in the local repository. So, for example:

fetch: +refs/heads/master:refs/remotes/origin/master

tells Git to map the master branch that exists in the remote repository (the source) to the origin/master branch in the local one (the destination).

The + character is optional and means that Git should update the destination branch even if it would require a merge commit (which shouldn't happen since you normally don't commit directly to the origin/master branch).

Pull Request Branches

Now that you know about the refspec syntax, let's talk about mapping the pull request branches from GitHub.

As you know, every pull request gets assigned a unique number within a given repository. What you may not know, however, is that this number ends up becoming the name of the branch associated to the pull request.

For example, a pull request with number 42 will get a branch reference named:

refs/pull/42

Notice how pull request branches are created in a subdirectory called pull in the repository hosted on GitHub.

If you wanted to map every pull request branch that exists in the remote repository on GitHub to a corresponding local branch with the same name, you would say:

fetch = +refs/pull/*/head:refs/pull/origin/*

where * is a wildcard character that matches any name. With this setting, next time you do git fetch in your local repository, Git will download all branch references that exist in the pull directory on GitHub and create corresponding branches in the local repository under the directory pull/origin.

This means that for our pull request 42, for example, the mapping becomes:

    GitHub        Your Repo
pull/42/head -> pull/origin/42

Remote Branches

Note that the pull/origin/* branches—while they do exist in your local repository—are not meant for you to commit to. They're called remote-tracking branches and are used by Git to literally keep track of a given branch that exist in a remote repository.

The documentation says it best:

Remote-tracking branches are references to the state of remote branches.

More specifically:

Think of them as bookmarks, to remind you where the branches in your remote repositories were the last time you connected to them.

You can't commit to a remote branch directly. If you want to move it forward, you must first create a local branch (i.e. one that exists only in your local repository) and associate it to the remote branch. From that point on, every time you do git pull or git push on that local branch, Git is going to update the corresponding remote tracking branch.

You can do that with a single command:

git checkout -b 42 pull/origin/42

This creates a local branch named 42 and associate it to the remote tracking branch pull/origin/42, which in turn is mapped to the pull/42 branch on GitHub. Here's how it looks like:

 Local      Remote        GitHub
  42 -> pull/origin/42 -> pull/42

The relationship between local branch and remote branch is expressed in the local repository's configuration file as:

[branch "42"]
remote = origin
merge = refs/pull/42/head

The relationship between the remote branch and the branch that's physically on another machine (i.e. on GitHub) is expressed by using the refspec syntax that we looked at in the beginning.

like image 194
Enrico Campidoglio Avatar answered Nov 15 '22 01:11

Enrico Campidoglio