git/refs/ . In Git, a head is a ref that points to the tip (latest commit) of a branch. You can view your repository's heads in the path . git/refs/heads/ . In this path you will find one file for each branch, and the content in each file will be the commit ID of the tip (most recent commit) of that branch.
When a repository has hundreds or thousands of tags, this one-file-per-ref format both wastes storage and hurts performance. This command is used to solve the storage and performance problem by storing the refs in a single file, $GIT_DIR/packed-refs .
git fetch is the command that tells your local git to retrieve the latest meta-data info from the original (yet doesn't do any file transferring. It's more like just checking to see if there are any changes available). git pull on the other hand does that AND brings (copy) those changes from the remote repository.
The git prune command is an internal housekeeping utility that cleans up unreachable or "orphaned" Git objects. Unreachable objects are those that are inaccessible by any refs. Any commit that cannot be accessed through a branch or tag is considered unreachable.
A refspec tells git how to map references from a remote to the local repo.
The value you listed was +refs/heads/*:refs/remotes/origin/* +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*
; so let's break that down.
You have two patterns with a space between them; this just means you're giving multiple rules. (The pro git book refers to this as two refspecs; which is probably technically more correct. However, you just about always have the ability to list multiple refspecs if you need to, so in day to day life it likely makes little difference.)
The first pattern, then, is +refs/heads/*:refs/remotes/origin/*
which has three parts:
+
means to apply the rule without failure even if doing so would move a target ref in a non-fast-forward manner. I'll come back to that.:
(but after the +
if there is one) is the "source" pattern. That's refs/heads/*
, meaning this rule applies to any remote reference under refs/heads
(meaning, branches).:
is the "destination" pattern. That's refs/remotes/origin/*
.So if the origin has a branch master
, represented as refs/heads/master
, this will create a remote branch reference origin/master
represented as refs/remotes/origin/master
. And so on for any branch name (*
).
So back to that +
... suppose the origin has
A --- B <--(master)
You fetch and, applying that refspec you get
A --- B <--(origin/master)
(If you applied typical tracking rules and did a pull
you also have master
pointed at B
.)
A --- B <--(origin/master)(master)
Now some things happen on the remote. Someone maybe did a reset
that erased B
, then committed C
, then forced a push. So the remote says
A --- C <--(master)
When you fetch, you get
A --- B
\
C
and git must decide whether to allow the move of origin/master
from B
to C
. By default it wouldn't allow this because it's not a fast-forward (it would tell you it rejected the pull for that ref), but because the rule starts with +
it will accept it.
A --- B <--(master)
\
C <--(origin/master)
(A pull will in this case result in a merge commit.)
The second pattern is similar, but for merge-requests
refs (which I assume is related to your server's implementation of PR's; I'm not familiar with it).
More about refspecs: https://git-scm.com/book/en/v2/Git-Internals-The-Refspec
A refspec tells git how to map references from a remote to the local repo.
With Git 2.29 (Q4 2020), a refspec can also tell Git what reference to exclude.
"git fetch
" and "git push
" support negative refspecs.
So not only can you fetch
selectively:
# Do not fetch any remote branch starting with 'm'
git fetch origin refs/heads/*:refs/remotes/origin/* ^refs/heads/m*
But you can even push
or push --prune
selectively:
# If I delete local branches, included b,
# those same branches will be deleted in the remote 'origin' repo.
# ... except for the remote branch b!
git push --prune origin refs/heads/* ^refs/heads/b
See commit c0192df (30 Sep 2020) by Jacob Keller (jacob-keller
).
(Merged by Junio C Hamano -- gitster
-- in commit 8e3ec76, 5 Oct 2020)
refspec
: add support for negative refspecsSigned-off-by: Jacob Keller
Both
fetch
andpush
support pattern refspecs which allow fetching or pushing references that match a specific pattern.
Because these patterns are globs, they have somewhat limited ability to express more complex situations.For example, suppose you wish to fetch all branches from a remote except for a specific one. To allow this, you must setup a set of refspecs which match only the branches you want.
Because refspecs are either explicit name matches, or simple globs, many patterns cannot be expressed.Add support for a new type of refspec, referred to as "negative" refspecs.
These are prefixed with a '
^
' and mean "exclude any ref matching this refspec
".
They can only have one "side" which always refers to the source.
- During a fetch, this refers to the name of the ref on the remote.
- During a push, this refers to the name of the ref on the local side.
With negative refspecs, users can express more complex patterns. For example:
git fetch origin refs/heads/*:refs/remotes/origin/* ^refs/heads/dontwant
will fetch all branches on
origin
intoremotes/origin
, but will exclude fetching the branch nameddontwant
.Refspecs today are commutative, meaning that order doesn't expressly matter.
Rather than forcing an implied order, negative refspecs will always be applied last.
That is, in order to match, a ref must match at least one positive refspec, and match none of the negative refspecs.
This is similar to how negative pathspecs work.
The documentation now includes:
A
<refspec>
may contain a*
in its<src>
to indicate a simple pattern match.
Such a refspec functions like a glob that matches any ref with the same prefix. A pattern<refspec>
must have a*
in both the<src>
and<dst>
. It will map refs to the destination by replacing the*
with the contents matched from the source.If a refspec is prefixed by
^
, it will be interpreted as a negative refspec.
Rather than specifying which refs to fetch or which local refs to update, such a refspec will instead specify refs to exclude.
A ref will be considered to match if it matches at least one positive refspec, and does not match any negative refspec.Negative refspecs can be useful to restrict the scope of a pattern refspec so that it will not include specific refs.
Negative refspecs can themselves be pattern refspecs. However, they may only contain a<src>
and do not specify a<dst>
.
Fully spelled out hex object names are also not supported.
See t5582-fetch-negative-refspec.sh
for more examples
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With