Suppose I have the following stanza in .git/config
:
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
With this configuration:
git fetch origin
will fetch all branches.git fetch origin my_branch
will fetch origin's copy of my_branch
and update the tracking branch at refs/remotes/origin/my_branch
.Now suppose I have the following stanza instead, which names two explicit branches that are not my_branch
.
[remote "origin"]
fetch = +refs/heads/master:refs/remotes/origin/master
fetch = +refs/heads/all-green:refs/remotes/origin/all-green
With this configuration:
git fetch origin
will only fetch master
and all-green
.git fetch origin my_branch
will fetch the branch, but not update any tracking branch. If I want to update the tracking branch, I must explicitly say git fetch origin my_branch:refs/remotes/origin/my_branch
.Is it possible to configure git
in such a way that the following two statements are true?
git fetch origin my_branch
will update local tracking branches according to the refspec in Scenario 1 for all possible values of my_branch.git fetch origin
fetches only those branches that have previously been explicitly fetched (e.g. they already have a remote-tracking branch) rather than all branches that match the refspec.In other words, I would like to use the refspec
to determine the branch mapping automatically when I give a remote branch name to fetch, but not to determine the set of branches that is fetched when I merely say git fetch origin
without a branch name.
My current approach is to just edit the git config (manually or using a script) for every remote branch I want to track, but I ask this question to see if there's a more direct way to get the behavior I want.
Suppose I have the following stanza in .git/config
:
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
With this configuration:
git fetch origin
will fetch all branches.git fetch origin my_branch
will fetch origin's copy of my_branch
and update the tracking branch at refs/remotes/origin/my_branch
.Now suppose I have the following stanza instead, which names two explicit branches that are not my_branch
.
[remote "origin"]
fetch = +refs/heads/master:refs/remotes/origin/master
fetch = +refs/heads/all-green:refs/remotes/origin/all-green
With this configuration:
git fetch origin
will only fetch master
and all-green
.git fetch origin my_branch
will fetch the branch, but not update any tracking branch. If I want to update the tracking branch, I must explicitly say git fetch origin my_branch:refs/remotes/origin/my_branch
.Is it possible to configure git
in such a way that the following two statements are true?
git fetch origin my_branch
will update local tracking branches according to the refspec in Scenario 1 for all possible values of my_branch.git fetch origin
fetches only those branches that have previously been explicitly fetched (e.g. they already have a remote-tracking branch) rather than all branches that match the refspec.In other words, I would like to use the refspec
to determine the branch mapping automatically when I give a remote branch name to fetch, but not to determine the set of branches that is fetched when I merely say git fetch origin
without a branch name.
My current approach is to just edit the git config (manually or using a script) for every remote branch I want to track, but I ask this question to see if there's a more direct way to get the behavior I want.
edit: this works fine but OP found the --refmap
option I'd never noticed, that makes a much better answer, this is still useful as context/samplecode so:
It's very easy to write a ~update the factory-default tracking branches even for branches I'm not usually tracking~ convenience, the payload is just
awk '$2=="branch" { print "git update-ref refs/remotes/origin/"$3,$1 }' \
$(git rev-parse --git-dir)/FETCH_HEAD | sh -x
and you can invoke that however you want. It might be your best option, because I think this in the fetch refspec docs
Unlike when pushing with git-push[1], there is no configuration which’ll amend these rules, and nothing like a
pre-fetch
hook analogous to thepre-receive
hook.
means "no." Which does make sense, fetching is often scripted for custom workflows already, some of them so common support has been provided in a factory-supplied convenience: git pull does any of several really common fetch-plus-custom-followup sequences.
For another option, you could also customize an alternate remote,
git config remote.onebranch.url $(git config remote.origin.url)
git config remote.onebranch.fetch +refs/heads/*:refs/remotes/origin/*
after which git fetch onebranch my_branch
will update the origin tracking branch if needed.
Given that the answer is "No", I am posting additional workarounds:
git config --global alias.fetchbranch "fetch --refmap=+refs/heads/*:refs/remotes/origin/*"
Add the following manually to the ~/.gitconfig
:
[alias]
ffetch = "!f() { git fetch --refmap=\"+refs/heads/*:refs/remotes/${1}/*\" \"$@\"; }; f"
Note that both of the above workarounds, as well as the accepted answer, do not cause git fetch origin
to correctly fetch the tracked branch.
git config
The only method that actually causes git fetch
without specifying a branch to automatically pick up updates appears to be adding the refspec into the git config:
remote_branch_name="$1"
remote="origin"
if [[ $# -gt 1 ]]; then
remote="$2"
fi
refspec="refs/heads/${remote_branch_name}:refs/remotes/origin/${remote_branch_name}"
# Check if this config already exists.
if git config --get "remote.${remote}.fetch" "$refspec"; then
>&2 echo "Branch ${remote_branch_name} from ${remote} is already tracked."
exit 0
fi
# Check if the remote has the branch.
if ! git fetch "$remote" "refs/heads/${remote_branch_name}" 2>/dev/null; then
>&2 echo "Branch ${remote_branch_name} does not exist on ${remote}."
exit 1
fi
# Actually add the refspec
git config --add "remote.${remote}.fetch" "+${refspec}"
# Do the initial fetch as a convenience.
git fetch "${remote}" "${remote_branch_name}"
I paired this with a second script to untrack:
remote_branch_name="$1"
remote="origin"
if [[ $# -gt 1 ]]; then
remote="$2"
fi
refspec="refs/heads/${remote_branch_name}:refs/remotes/origin/${remote_branch_name}"
# For no-op case.
if ! git config --get "remote.${remote}.fetch" "$refspec"; then
>&2 echo "Branch ${remote_branch_name} from ${remote} is already untracked."
exit 0
fi
git config --unset-all remote.origin.fetch "\+${refspec}"
my_branch
with the stringTimRoberts/branch1
or the stringmerlin2011/branch2
, it should still work. – merlin2011 Commented Feb 1 at 5:10git myfetch origin branchfoo
to: a. just updateorigin/branchfoo
ref ? b. updateorigin/branchfoo
and also create a local tracking branch ? or c. addbranchfoo
in the list of default branches in the.git/config
file for that remote ? – LeGEC Commented Feb 1 at 9:03! ...
,...
can be any shell command, 2. if you create an executable script namedgit-foo
, make it executable and somehow accessible from the PATH, then you can typegit foo ...
as if it were an alias or a new subcommand – LeGEC Commented Feb 1 at 9:05git branch
, but ifc
just means the branch gets updated by default when I dogit fetch origin
, then I also meanc
. – merlin2011 Commented Feb 1 at 9:12