This teaches the deepest part of the callchain for "git push" (and
"git send-pack") to enforce "the old value of the ref must be this,
otherwise fail this push" (aka "compare-and-swap" / "--lockref").
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This plugs the push_cas_option data collected by the command line
option parser to the transport system with a new function
apply_push_cas(), which is called after match_push_refs() has
already been called.
At this point, we know which remote we are talking to, and what
remote refs we are going to update, so we can fill in the details
that may have been missing from the command line, such as
(1) what abbreviated refname the user gave us matches the actual
refname at the remote; and
(2) which remote-tracking branch in our local repository to read
the value of the object to expect at the remote.
to populate the old_sha1_expect[] field of each of the remote ref.
As stated in the documentation, the use of remote-tracking branch
as the default is a tentative one, and we may come up with a better
logic as we gain experience.
Still nobody uses this information, which is the topic of the next
patch.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Update "git push" and "git send-pack" to parse this commnd line
option.
The intended sematics is:
* "--force-with-lease" alone, without specifying the details, will
protect _all_ remote refs that are going to be updated by
requiring their current value to be the same as some reasonable
default, unless otherwise specified;
* "--force-with-lease=refname", without specifying the expected
value, will protect that refname, if it is going to be updated,
by requiring its current value to be the same as some reasonable
default.
* "--force-with-lease=refname:value" will protect that refname, if
it is going to be updated, by requiring its current value to be
the same as the specified value; and
* "--no-force-with-lease" will cancel all the previous --force-with-lease on the
command line.
For now, "some reasonable default" is tentatively defined as "the
value of the remote-tracking branch we have for the ref of the
remote being updated", and it is an error if we do not have such a
remote-tracking branch. But this is known to be fragile, its use is
not yet recommended, and hopefully we will find more reasonable
default as we gain experience with this feature. The manual marks
the feature as experimental unless the expected value is specified
explicitly for this reason.
Because the command line options are parsed _before_ we know which
remote we are pushing to, there needs further processing to the
parsed data after we instantiate the transport object to:
* expand "refname" given by the user to a full refname to be
matched with the list of "struct ref" used in match_push_refs()
and set_ref_status_for_push(); and
* learning the actual local ref that is the remote-tracking branch
for the specified remote ref.
Further, some processing need to be deferred until we find the set
of remote refs and match_push_refs() returns in order to find the
ones that need to be checked after explicit ones have been processed
for "--force-with-lease" (no specific details).
These post-processing will be the topic of the next patch.
This option was originally called "cas" (for "compare and swap"),
the name which nobody liked because it was too technical. The
second attempt called it "lockref" (because it is conceptually like
pushing after taking a lock) but the word "lock" was hated because
it implied that it may reject push by others, which is not the way
this option works. This round calls it "force-with-lease". You
assume you took the lease on the ref when you fetched to decide what
the rebased history should be, and you can push back only if the
lease has not been broken.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The definition of "struct ref" in "cache.h", a header file so
central to the system, always confused me. This structure is not
about the local ref used by sha1-name API to name local objects.
It is what refspecs are expanded into, after finding out what refs
the other side has, to define what refs are updated after object
transfer succeeds to what values. It belongs to "remote.h" together
with "struct refspec".
While we are at it, also move the types and functions related to the
Git transport connection to a new header file connect.h
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The first line of the function checks that the remote-name contains a
slash ('/'), and sets the "slash" variable accordingly. The only caller
of read_branches_file() is remote_get_1(); the calling codepath is
guarded by valid_remote_nick(), which checks that the remote does not
contain a slash. Therefore, the "slash" variable can never be set:
remove the dead code that assumes otherwise.
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This new configuration variable overrides `remote.pushdefault` and
`branch.<name>.remote` for pushes. When you pull from one
place (e.g. your upstream) and push to another place (e.g. your own
publishing repository), you would want to set `remote.pushdefault` to
specify the remote to push to for all branches, and use this option to
override it for a specific branch.
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
Reviewed-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This new configuration variable defines the default remote to push to,
and overrides `branch.<name>.remote` for all branches. It is useful
in the typical triangular-workflow setup, where the remote you're
fetching from is different from the remote you're pushing to.
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
Reviewed-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Currently, do_push() in push.c calls remote_get(), which gets the
configured remote for fetching and pushing. Replace this call with a
call to pushremote_get() instead, a new function that will return the
remote configured specifically for pushing. This function tries to
work with the string pushremote_name, before falling back to the
codepath of remote_get(). This patch has no visible impact, but
serves to enable future patches to introduce configuration variables
to set pushremote_name. For example, you can now do the following in
handle_config():
if (!strcmp(key, "remote.pushdefault"))
git_config_string(&pushremote_name, key, value);
Then, pushes will automatically go to the remote specified by
remote.pushdefault.
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
Reviewed-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
A small segment where handle_config() parses the branch.remote
configuration variable can be simplified using git_config_string().
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
Reviewed-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Allows requests to fetch objects at any tip of refs (including
hidden ones). It seems that there may be use cases even outside
Gerrit (e.g. $gmane/215701).
* jc/fetch-raw-sha1:
fetch: fetch objects by their exact SHA-1 object names
upload-pack: optionally allow fetching from the tips of hidden refs
fetch: use struct ref to represent refs to be fetched
parse_fetch_refspec(): clarify the codeflow a bit
The new option "--follow-tags" tells "git push" to push annotated
tags that are missing from the other side and that can be reached by
the history that is otherwise pushed out.
For example, if you are using the "simple", "current", or "upstream"
push, you would ordinarily push the history leading to the commit at
your current HEAD and nothing else. With this option, you would
also push all annotated tags that can be reached from that commit to
the other side.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
In ancient times, we used to disallow the same source ref to be
pushed to more than one places, e.g. "git push there master:master
master:naster" was disallowed. We later lifted this restriction
with db27ee6392 (send-pack: allow the same source to be pushed
more than once., 2005-08-06) and there no longer is anybody that
sets peer_ref for the source side of the ref list in the push
codepath since then.
Remove one leftover no-op in a loop that iterates over the source
side of ref list (i.e. our local ref) to see if it can/should be
sent to a matching destination ref while skipping ones that is
marked with peer_ref (which will never exist, so we do not skip
anything).
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Teach "git fetch" to accept an exact SHA-1 object name the user may
obtain out of band on the LHS of a pathspec, and send it on a "want"
message when the server side advertises the allow-tip-sha1-in-want
capability.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Most parts of the cascaded if/else if/... checked an allowable
condition but some checked forbidden conditions. This makes adding
new allowable conditions unnecessarily inconvenient.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Improve error and advice messages given locally when "git push"
refuses when it cannot compute fast-forwardness by separating these
cases from the normal "not a fast-forward; merge first and push
again" case.
* jc/push-reject-reasons:
push: finishing touches to explain REJECT_ALREADY_EXISTS better
push: introduce REJECT_FETCH_FIRST and REJECT_NEEDS_FORCE
push: further simplify the logic to assign rejection reason
push: further clean up fields of "struct ref"
When we push to update an existing ref, if:
* the object at the tip of the remote is not a commit; or
* the object we are pushing is not a commit,
it won't be correct to suggest to fetch, integrate and push again,
as the old and new objects will not "merge". We should explain that
the push must be forced when there is a non-committish object is
involved in such a case.
If we do not have the current object at the tip of the remote, we do
not even know that object, when fetched, is something that can be
merged. In such a case, suggesting to pull first just like
non-fast-forward case may not be technically correct, but in
practice, most such failures are seen when you try to push your work
to a branch without knowing that somebody else already pushed to
update the same branch since you forked, so "pull first" would work
as a suggestion most of the time. And if the object at the tip is
not a commit, "pull first" will fail, without making any permanent
damage. As a side effect, it also makes the error message the user
will get during the next "push" attempt easier to understand, now
the user is aware that a non-commit object is involved.
In these cases, the current code already rejects such a push on the
client end, but we used the same error and advice messages as the
ones used when rejecting a non-fast-forward push, i.e. pull from
there and integrate before pushing again.
Introduce new rejection reasons and reword the messages
appropriately.
[jc: with help by Peff on message details]
Signed-off-by: Junio C Hamano <gitster@pobox.com>
First compute the reason why this push would fail if done without
"--force", and then fail it by assigning that reason when the push
was not forced (or if there is no reason to require force, allow it
to succeed).
Record the fact that the push was forced in the forced_update field
only when the push would have failed without the option.
The code becomes shorter, less repetitive and easier to read this
way, especially given that the set of rejection reasons will be
extended in a later patch.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The "nonfastforward" and "update" fields are only used while
deciding what value to assign to the "status" locally in a single
function. Remove them from the "struct ref".
The "requires_force" field is not used to decide if the proposed
update requires a --force option to succeed, or to record such a
decision made elsewhere. It is used by status reporting code that
the particular update was "forced". Rename it to "forced_update",
and move the code to assign to it around to further clarify how it
is used and what it is used for.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Regression fix to stop "git push" complaining "target ref already
exists", when it is not the real reason the command rejected the
request (e.g. non-fast-forward).
* cr/push-force-tag-update:
push: fix "refs/tags/ hierarchy cannot be updated without --force"
When pushing to update a branch with a commit that is not a
descendant of the commit at the tip, a wrong message "already
exists" was given, instead of the correct "non-fast-forward", if we
do not have the object sitting in the destination repository at the
tip of the ref we are updating.
The primary cause of the bug is that the check in a new helper
function is_forwardable() assumed both old and new objects are
available and can be checked, which is not always the case.
The way the caller uses the result of this function is also wrong.
If the helper says "we do not want to let this push go through", the
caller unconditionally translates it into "we blocked it because the
destination already exists", which is not true at all in this case.
Fix this by doing these three things:
* Remove unnecessary not_forwardable from "struct ref"; it is only
used inside set_ref_status_for_push();
* Make "refs/tags/" the only hierarchy that cannot be replaced
without --force;
* Remove the misguided attempt to force that everything that
updates an existing ref has to be a commit outside "refs/tags/"
hierarchy.
The policy last one tried to implement may later be resurrected and
extended to ensure fast-forwardness (defined as "not losing
objects", extending from the traditional "not losing commits from
the resulting history") when objects that are not commit are
involved (e.g. an annotated tag in hierarchies outside refs/tags),
but such a logic belongs to "is this a fast-forward?" check that is
done by ref_newer(); is_forwardable(), which is now removed, was not
the right place to do so.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
"git fetch --mirror" and fetch that uses other forms of refspec with
wildcard used to attempt to update a symbolic ref that match the
wildcard on the receiving end, which made little sense (the real ref
that is pointed at by the symbolic ref would be updated anyway).
Symbolic refs no longer are affected by such a fetch.
* jc/fetch-ignore-symref:
fetch: ignore wildcarded refspecs that update local symbolic refs
Avoid false error from an attempt to update local symbolic ref via
fetch.
* jc/fetch-ignore-symref:
fetch: ignore wildcarded refspecs that update local symbolic refs
Require "-f" for push to update a tag, even if it is a fast-forward.
* cr/push-force-tag-update:
push: allow already-exists advice to be disabled
push: rename config variable for more general use
push: cleanup push rules comment
push: clarify rejection of update to non-commit-ish
push: require force for annotated tags
push: require force for refs under refs/tags/
push: flag updates that require force
push: keep track of "update" state separately
push: add advice for rejected tag reference
push: return reject reasons as a bitset
In a repository cloned from somewhere else, you typically have a
symbolic ref refs/remotes/origin/HEAD pointing at the 'master'
remote-tracking ref that is next to it. When fetching into such a
repository with "git fetch --mirror" from another repository that
was similarly cloned, the implied wildcard refspec refs/*:refs/*
will end up asking to update refs/remotes/origin/HEAD with the
object at refs/remotes/origin/HEAD at the remote side, while asking
to update refs/remotes/origin/master the same way. Depending on the
order the two updates happen, the latter one would find that the
value of the ref before it is updated has changed from what the code
expects.
When the user asks to update the underlying ref via the symbolic ref
explicitly without using a wildcard refspec, e.g. "git fetch $there
refs/heads/master:refs/remotes/origin/HEAD", we should still let him
do so, but when expanding wildcard refs, it will result in a more
intuitive outcome if we simply ignore local symbolic refs.
As the purpose of the symbolic ref refs/remotes/origin/HEAD is to
follow the ref it points at (e.g. refs/remotes/origin/master), its
value would change when the underlying ref is updated.
Earlier commit da3efdb (receive-pack: detect aliased updates which
can occur with symrefs, 2010-04-19) fixed a similar issue for "git
push".
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Finishing touch to allow the new advice message squelched
with an advice.* configuration variable.
* mm/status-push-pull-advise:
status: respect advice.statusHints for ahead/behind advice
If the user has unset advice.statusHints, we already
suppress the "use git reset to..." hints in each stanza. The
new "use git push to publish..." hint is the same type of
hint. Let's respect statusHints for it, rather than making
the user set yet another advice flag.
Signed-off-by: Jeff King <peff@peff.net>
Acked-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Rewrite to remove inter-dependencies amongst the rules.
Signed-off-by: Chris Rorvick <chris@rorvick.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Pushes must already (by default) update to a commit-ish due to the fast-
forward check in set_ref_status_for_push(). But rejecting for not being
a fast-forward suggests the situation can be resolved with a merge.
Flag these updates (i.e., to a blob or a tree) as not forwardable so the
user is presented with more appropriate advice.
While updating *from* a tag object is potentially destructive, updating
*to* a tag is not. Additionally, a push to the refs/tags/ hierarchy is
already excluded from fast-forwarding, and refs/heads/ is protected from
anything but commit objects by a check in write_ref_sha1(). Thus
someone fast-forwarding to a tag is probably not doing so by accident.
Since updating to a tag is benign and unlikely to cause confusion, allow
it in case someone finds the behavior useful.
Signed-off-by: Chris Rorvick <chris@rorvick.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Do not allow fast-forwarding of references that point to a tag object.
Updating from a tag is potentially destructive since it would likely
leave the tag dangling. Disallowing updates to a tag also makes sense
semantically and is consistent with the behavior of lightweight tags.
Signed-off-by: Chris Rorvick <chris@rorvick.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
References are allowed to update from one commit-ish to another if the
former is an ancestor of the latter. This behavior is oriented to
branches which are expected to move with commits. Tag references are
expected to be static in a repository, though, thus an update to
something under refs/tags/ should be rejected unless the update is
forced.
Signed-off-by: Chris Rorvick <chris@rorvick.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Add a flag for indicating an update to a reference requires force.
Currently the `nonfastforward` flag is used for this when generating the
status message. A separate flag insulates dependent logic from the
details of set_ref_status_for_push().
Signed-off-by: Chris Rorvick <chris@rorvick.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
If the reference exists on the remote and it is not being removed, then
mark as an update. This is in preparation for handling tags (lightweight
and annotated) exceptionally.
Signed-off-by: Chris Rorvick <chris@rorvick.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Advising the user to fetch and merge only makes sense if the rejected
reference is a branch. If none of the rejections are for branches, just
tell the user the reference already exists.
Signed-off-by: Chris Rorvick <chris@rorvick.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
For a fetch refspec (or the result of applying wildcard on one), we
always want the RHS to map to something inside "refs/" hierarchy.
This was split out from discarded jc/maint-push-refs-all topic.
* jc/maint-fetch-tighten-refname-check:
get_fetch_map(): tighten checks on dest refs
The code to check the refname we store the fetched result locally did not
bother checking the first 5 bytes of it, presumably assuming that it
always begin with "refs/". For a fetch refspec (or the result of applying
wildcard on one), we always want the RHS to map to something inside
"refs/" hierarchy, so let's spell that rule out in a more explicit way.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The error message from "git push $there :bogo" mentioned we tried
and failed to guess what ref is being deleted based on the LHS of
the refspec, which we don't.
# By Jeff King
* jk/push-delete-ref-error-message:
push: don't guess at qualifying remote refs on deletion
When we try to push a ref and the right-hand side of the
refspec does not find a match, we try to create it. If it is
not fully qualified, we try to guess where it would go in
the refs hierarchy based on the left-hand source side. If
the source side is not a ref, then we give up and give a
long explanatory message.
For deletions, however, this doesn't make any sense. We
would never want to create on the remote side, and if an
unqualified ref can't be matched, it is simply an error. The
current code handles this already because the left-hand side
is empty, and therefore does not give us a hint as to where
the right-hand side should go, and we properly error out.
Unfortunately, the error message is the long "we tried to
qualify this, but the source side didn't let us guess"
message, which is quite confusing.
Instead, we can just be more succinct and say "we can't
delete this because we couldn't find it". So before:
$ git push origin :bogus
error: unable to push to unqualified destination: bogus
The destination refspec neither matches an existing ref on the remote nor
begins with refs/, and we are unable to guess a prefix based on the source ref.
error: failed to push some refs to '$URL'
and now:
$ git push origin :bogus
error: unable to delete 'bogus': remote ref does not exist
error: failed to push some refs to '$URL'
It is tempting to also catch a fully-qualified ref like
"refs/heads/bogus" and generate the same error message.
However, that currently does not error out at all, and
instead gets sent to the remote side, which typically
generates a warning:
$ git push origin:refs/heads/bogus
remote: warning: Deleting a non-existent ref.
To $URL
- [deleted] bogus
While it would be nice to catch this error early, a
client-side error would mean aborting the push entirely and
changing push's exit code. For example, right now you can
do:
$ git push origin refs/heads/foo refs/heads/bar
and end up in a state where "foo" and "bar" are deleted,
whether both of them currently exist or not (and see an
error only if we actually failed to contact the server).
Generating an error would cause a regression for this use
case.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Since we store lists of refs as linked lists, we can use
llist_mergesort to efficiently sort them.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When pushing groups of refs to a remote, there is no simple way to remove
old refs that still exist at the remote that is no longer updated from us.
This will allow us to remove such refs from the remote.
With this change, running this command
$ git push --prune remote refs/heads/*:refs/remotes/laptop/*
removes refs/remotes/laptop/foo from the remote if we do not have branch
"foo" locally anymore.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Will be useful in next patches. No functional changes.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The function match_name_with_pattern() is called twice, once to see if a
pattern matches with the name, and again to learn what the matched pattern
maps the name to. Since check_pattern_match() is only used in one place,
we can just reorganize it to make a single call and fetch the values at
the same time.
This changes the meaning of check_pattern_match() that used to check which
pattern in the array of refspecs matched the given ref, to return the name
of the remote ref the given ref is mapped to.
Rename it to get_ref_match() which actually describes more closely what
it's actually doing now.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
So that we can reuse src later on. No functional changes.
Will be useful in next patches.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Function format_tracking_info in remote.c is called by
wt_status_print_tracking in wt-status.c, which will print
branch tracking message in git-status. git-checkout also
show these messages through it's report_tracking function.
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
resolve_ref() may return a pointer to a shared buffer and can be
overwritten by the next resolve_ref() calls. Callers need to
pay attention, not to keep the pointer when the next call happens.
Rename with "_unsafe" suffix to warn developers (or reviewers) before
introducing new call sites.
This patch is generated using the following command
git grep -l 'resolve_ref(' -- '*.[ch]'|xargs sed -i 's/resolve_ref(/resolve_ref_unsafe(/g'
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
resolve_ref() may return a pointer to a static buffer, which is not
safe for long-term use because if another resolve_ref() call happens,
the buffer may be changed. Many call sites though do not care about
this buffer. They simply check if the return value is NULL or not.
Convert all these call sites to new wrappers to reduce resolve_ref()
calls from 57 to 34. If we change resolve_ref() prototype later on
to avoid passing static buffer out, this helps reduce changes.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>