Reset all branches of a local repo to be the same as remote
First this is different because this is for all branches not one
You can use a script which which will loop over your branches and then do what ever you want on each one:
# Loop on all the desired branches
for ref in $(git branch -a)
do
# ... DO ANYTHING YOU NEED HERE
# You have the $ref which stores the branch name
# ex: remotes/origin/master
done
Is there a better ans simple solution?
Yes, simply clone the project again and you will have the same content as your origin.
This is exactly what you do manually per branch.
Note:
You can fetch all the data at once using this command:
# Fetch all remotes, branches and remove deledted content
git fetch --all --prune
Just wrote a small tool that does this.
Advantages of this tool:
- Supports multiple remotes in one repository.
- Supports having different names for the local and tracking branches.
- No error-prone regex parsing/editing.
Here's the script:
#!/bin/bash
ENOENT=2
EEXIST=17
curref=$(git symbolic-ref HEAD 2>&-)
fetch_all() {
git fetch --all
ret=$?
[ "$ret" -eq 0 ] || {
return "$ret"
}
}
hard_reset_all() {
ret=0
while read -r line; do
branch=$(echo "$line" | cut -c 8- | rev | cut -c 8- | rev)
remote=$(git config --local --get "branch.$branch.remote")
upstream=$(git config --local --get "branch.$branch.merge" | cut -c 12-)
if ! git rev-parse --verify --quiet "$remote/$upstream" 1>&- 2>&-; then
ret=$(( $ret | $ENOENT ))
echo "Branch $branch"
echo " skipped: upstream is absent"
continue
fi
if [ -z "$(git log --oneline -1 "$branch...$remote/$upstream")" ]; then
continue
fi
echo "Branch $branch"
echo " $(git log --oneline -1 $branch)"
if [ "refs/heads/$branch" = "$curref" ]; then
git reset --hard "$remote/$upstream" 1>&- 2>&-
else
git update-ref "refs/heads/$branch" "$remote/$upstream" 1>&- 2>&-
fi
echo " -> $(git log --oneline -1 $remote/$upstream)"
done < <(git config --local --name-only --get-regex '^branch.*remote$')
return "$ret"
}
fetch_all
excode=$?
[ "$excode" -eq 0 ] || {
exit "$excode"
}
if output=$(git status --porcelain) && [ -n "$output" ]; then
echo "Skipped: repo is not clean"
exit $EEXIST
fi
hard_reset_all
excode=$?
[ "$excode" -eq 0 ] || {
exit "$excode"
}
Why not just delete all local branches, and then whenever a remote branch gets re-checked-out, you'll be synced?
# BE CAREFUL!!!
# THIS COMMAND WIPES OUT ALL LOCAL BRANCHES
git branch | xargs git branch -D
xargs runs the provided command against every line of stdin, in this case "git branch -D" against every line of the original "git branch" command.
The "git branch -D" command will fail for current branch, but every other branch will get wiped.
Alternatively you could cook something up with "xargs" that runs "git branch -f" to force-set every local branch to its remote copy, but I think the "git branch -D" approach above is the simplest, and also the most straight-forward as far as consequences, potential hazards are concerned.