mirror of
https://github.com/git-for-windows/git.git
synced 2026-06-27 22:28:38 -05:00
push: suggest <remote> <branch> for a slash slip
When pushing the 'main' branch to the remote 'origin', i.e.,
$ git push origin main
it is easy to mistakenly write
$ git push origin/main
That is parsed as the repository to push to, and since 'origin/main'
is neither a configured remote nor a path it dies with:
fatal: 'origin/main' does not appear to be a git repository
Often 'origin/main' does not exist as a repository, so the command
fails without doing any harm, but it gives no hint that a space was
meant instead of a slash and can leave the user puzzled.
When the argument is not an existing path or configured remote but
its part before the first slash names one, suggest the intended
'<remote> <branch>' form:
$ git push origin main
The suggestion is shown as advice so it can be silenced with
advice.pushRepoLooksLikeRef.
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
committed by
Junio C Hamano
parent
35d04b7c30
commit
39c960270d
@@ -90,6 +90,11 @@ all advice messages.
|
||||
Shown when linkgit:git-push[1] rejects a forced update of
|
||||
a branch when its remote-tracking ref has updates that we
|
||||
do not have locally.
|
||||
pushRepoLooksLikeRef::
|
||||
Shown when the repository given to linkgit:git-push[1] is not
|
||||
a configured remote but looks like a `<remote>/<branch>` ref,
|
||||
suggesting that the remote and branch be given as separate
|
||||
arguments.
|
||||
pushUnqualifiedRefname::
|
||||
Shown when linkgit:git-push[1] gives up trying to
|
||||
guess based on the source and destination refs what
|
||||
|
||||
1
advice.c
1
advice.c
@@ -69,6 +69,7 @@ static struct {
|
||||
[ADVICE_PUSH_NON_FF_CURRENT] = { "pushNonFFCurrent" },
|
||||
[ADVICE_PUSH_NON_FF_MATCHING] = { "pushNonFFMatching" },
|
||||
[ADVICE_PUSH_REF_NEEDS_UPDATE] = { "pushRefNeedsUpdate" },
|
||||
[ADVICE_PUSH_REPO_LOOKS_LIKE_REF] = { "pushRepoLooksLikeRef" },
|
||||
[ADVICE_PUSH_UNQUALIFIED_REF_NAME] = { "pushUnqualifiedRefName" },
|
||||
[ADVICE_PUSH_UPDATE_REJECTED] = { "pushUpdateRejected" },
|
||||
[ADVICE_PUSH_UPDATE_REJECTED_ALIAS] = { "pushNonFastForward" }, /* backwards compatibility */
|
||||
|
||||
1
advice.h
1
advice.h
@@ -36,6 +36,7 @@ enum advice_type {
|
||||
ADVICE_PUSH_NON_FF_CURRENT,
|
||||
ADVICE_PUSH_NON_FF_MATCHING,
|
||||
ADVICE_PUSH_REF_NEEDS_UPDATE,
|
||||
ADVICE_PUSH_REPO_LOOKS_LIKE_REF,
|
||||
ADVICE_PUSH_UNQUALIFIED_REF_NAME,
|
||||
ADVICE_PUSH_UPDATE_REJECTED,
|
||||
ADVICE_PUSH_UPDATE_REJECTED_ALIAS,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "advice.h"
|
||||
#include "branch.h"
|
||||
#include "config.h"
|
||||
#include "dir.h"
|
||||
#include "environment.h"
|
||||
#include "gettext.h"
|
||||
#include "hex.h"
|
||||
@@ -662,6 +663,29 @@ static int push_multiple(struct string_list *list,
|
||||
return result;
|
||||
}
|
||||
|
||||
static void die_if_repo_looks_like_ref(const char *repo)
|
||||
{
|
||||
const char *slash = strchr(repo, '/');
|
||||
struct strbuf name = STRBUF_INIT;
|
||||
int code;
|
||||
|
||||
if (!slash || !slash[1] || file_exists(repo))
|
||||
return;
|
||||
|
||||
strbuf_add(&name, repo, slash - repo);
|
||||
if (!remote_is_configured(remote_get(name.buf), 0)) {
|
||||
strbuf_release(&name);
|
||||
return;
|
||||
}
|
||||
|
||||
code = die_message(_("'%s' is not a valid push target"), repo);
|
||||
advise_if_enabled(ADVICE_PUSH_REPO_LOOKS_LIKE_REF,
|
||||
_("Did you mean to use: git push %s %s?"),
|
||||
name.buf, slash + 1);
|
||||
strbuf_release(&name);
|
||||
exit(code);
|
||||
}
|
||||
|
||||
int cmd_push(int argc,
|
||||
const char **argv,
|
||||
const char *prefix,
|
||||
@@ -744,6 +768,11 @@ int cmd_push(int argc,
|
||||
|
||||
if (repo) {
|
||||
if (!add_remote_or_group(repo, &remote_group)) {
|
||||
struct remote *r;
|
||||
|
||||
if (advice_enabled(ADVICE_PUSH_REPO_LOOKS_LIKE_REF))
|
||||
die_if_repo_looks_like_ref(repo);
|
||||
|
||||
/*
|
||||
* Not a configured remote name or group name.
|
||||
* Try treating it as a direct URL or path, e.g.
|
||||
@@ -753,7 +782,7 @@ int cmd_push(int argc,
|
||||
* from the URL so the loop below can handle it
|
||||
* identically to a named remote.
|
||||
*/
|
||||
struct remote *r = pushremote_get(repo);
|
||||
r = pushremote_get(repo);
|
||||
if (!r)
|
||||
die(_("bad repository '%s'"), repo);
|
||||
string_list_append(&remote_group, r->name);
|
||||
|
||||
@@ -54,6 +54,37 @@ test_expect_success 'detect empty remote with targeted refspec' '
|
||||
grep "fatal: bad repository ${SQ}${SQ}" stderr
|
||||
'
|
||||
|
||||
test_expect_success 'suggest <remote> <branch> for a <remote>/<branch> slip' '
|
||||
test_must_fail git push origin/main 2>stderr &&
|
||||
grep "${SQ}origin/main${SQ} is not a valid push target" stderr &&
|
||||
grep "hint: Did you mean to use: git push origin main?" stderr &&
|
||||
test_must_fail git -c advice.pushRepoLooksLikeRef=false push origin/main 2>stderr &&
|
||||
! grep "Did you mean" stderr
|
||||
'
|
||||
|
||||
test_expect_success 'suggest <remote> <branch> when the branch has slashes' '
|
||||
test_must_fail git push origin/feature/x 2>stderr &&
|
||||
grep "hint: Did you mean to use: git push origin feature/x?" stderr
|
||||
'
|
||||
|
||||
test_expect_success 'no suggestion when prefix is not a configured remote' '
|
||||
test_must_fail git push not-a-remote/main 2>stderr &&
|
||||
! grep "Did you mean" stderr
|
||||
'
|
||||
|
||||
test_expect_success 'no suggestion for a trailing slash with no branch' '
|
||||
test_must_fail git push origin/ 2>stderr &&
|
||||
! grep "Did you mean" stderr
|
||||
'
|
||||
|
||||
test_expect_success 'no suggestion when the argument is an existing path' '
|
||||
test_when_finished "rm -rf origin" &&
|
||||
git init --bare origin/main &&
|
||||
git push origin/main HEAD:refs/heads/pushed 2>stderr &&
|
||||
! grep "Did you mean" stderr &&
|
||||
git -C origin/main rev-parse --verify refs/heads/pushed
|
||||
'
|
||||
|
||||
test_expect_success 'detect ambiguous refs early' '
|
||||
git branch foo &&
|
||||
git tag foo &&
|
||||
|
||||
Reference in New Issue
Block a user