Comment remplacer une branche locale par une branche distante entièrement dans Git?

779

J'ai deux branches:

  1. branche locale (celle avec laquelle je travaille)
  2. branche distante (publique, seuls les commits bien testés y vont)

Récemment, j'ai sérieusement gâché ma succursale locale.

Comment pourrais-je remplacer entièrement la branche locale par la branche distante, afin de pouvoir continuer mon travail à partir de l'emplacement actuel de la branche distante?

J'ai déjà recherché SO et la vérification de la succursale distante localement n'a aucun effet.

YemSalat
la source
1
Je sais que la réponse acceptée a 1280 votes positifs, mais vous devriez vraiment envisager de changer la réponse acceptée par celle de @TTT.
Jamie

Réponses:

1289
  1. Assurez-vous d'avoir vérifié la branche que vous remplacez (d'après le commentaire de Zoltán ).
  2. En supposant que le maître est la branche locale que vous remplacez et que "origine / maître" est la branche distante que vous souhaitez réinitialiser:

    git reset --hard origin/master
    

Cela met à jour votre branche HEAD locale pour qu'elle soit la même révision que origin / master et --hardsynchronise également cette modification dans l'index et l'espace de travail.

araqnid
la source
4
Merci pour votre suggestion, j'ai tellement peur d'avoir déjà utilisé --hard et --force, j'ai donc choisi la solution qui ne les utilise pas.
YemSalat
13
@KonstantinLevin: ah oui, la dénomination de ces options est plutôt irritante. git resetpar défaut, vous rejoindrez votre branche actuelle et synchroniserez l'index. --softsautera la mise à jour de l'index, --hardsynchronisera également l'espace de travail. Ma propre expérience utilise la --hardplupart du temps, sauf quand je veux annuler le dernier commit (qui est juste git reset HEAD^)
araqnid
9
Après avoir plus d'expérience avec git, je suis convaincu que c'est une meilleure solution, merci.
YemSalat
24
vous devrez probablement chercher d'abord:git fetch origin remote_branch
b1r3k
53
Vous devez noter que cela remplacera la branche sur laquelle vous êtes actuellement avec le contenu de master . Donc, si vous êtes par exemple sur une branche de fonctionnalité, elle remplacera toutes ses validations par master, alors assurez-vous d'avoir vérifié la branche que vous remplacez en premier.
Zoltán
218

C'est aussi simple que trois étapes:

  1. Supprimez votre succursale locale: git branch -d local_branch
  2. Récupérez la dernière branche distante: git fetch origin remote_branch
  3. Reconstruisez la branche locale basée sur celle distante: git checkout -b local_branch origin/remote_branch
Adam Smith
la source
7
En fait, ce que @araqnid a dit est juste et plus concis. Je l'ai testé et vous pouvez également l'essayer.
adamsmith
Wow, le git checkout -b local_branch origin / remote_branch est génial! J'ai toujours fait cela dans deux commandes séparées. Merci!
kendepelchin
11
Vous devrez peut-être le faire git branch -D local_branchdans la première étape si votre branche n'est pas fusionnée.
szeryf
merci, j'ai eu du mal à utiliser gitflow, après avoir publié une branche puis l'avoir finie, je voulais aller dans la branche supprimée, et votre solution était la seule qui fonctionnait, pull ne semble pas fonctionner .. ou je mave Je ne l'ai pas bien utilisé -
Decebal
2
nous devons nous assurer que la branche actuelle n'est pas celle qui doit être supprimée.
a_secenthusiast
43
git branch -D <branch-name>
git fetch <remote> <branch-name>
git checkout -b <branch-name> --track <remote>/<branch-name>
Sailesh
la source
Que fait la partie --track?
eonist
3
@GitSync, c'est ce qui est git help branchdit --track. When creating a new branch, set up branch.<name>.remote and branch.<name>.merge configuration entries to mark the start-point branch as "upstream" from the new branch. This configuration will tell git to show the relationship between the two branches in git status and git branch -v. Furthermore, it directs git pull without arguments to pull from the upstream when the new branch is checked out. J'ai corrigé cette commande dans la réponse. Merci d'avoir soulevé ce point.
Sailesh
Donc, en termes simples: il ajoute l'URL distante à la nouvelle branche. Ils sont donc synchronisés pour toujours. Pour ainsi dire.
eonist
2
Vous pouvez dire que c'est juste pour plus de commodité. Si vous le faites git status, il signalera si votre succursale locale est devant ou derrière la succursale distante si vous les avez associés. De plus, vous pouvez faire git pull(ou push) au lieu de plein git pull <remote> <branch>si vous avez déjà configuré votre branche pour suivre <remote/branch>.
Sailesh
22

Remplacez tout par la branche distante; mais , à partir du même commit, votre branche locale est activée:

git reset --hard origin/some-branch

OU , obtenez les dernières nouvelles de la succursale distante et remplacez tout:

git fetch origin some-branch
git reset --hard FETCH_HEAD

En passant, si nécessaire, vous pouvez effacer les fichiers et répertoires non suivis que vous n'avez pas encore validés:

git clean -fd
un peu moins
la source
La git cleancommande l'a fait pour moi. git reset hard origin/mastern'effacez pas les fichiers non suivis. Merci!
Mornor
9

La façon la plus sûre et la plus complète de remplacer la branche locale actuelle par la télécommande:

git stash
git merge --abort
git rebase --abort
git branch -M yourBranch replaced_yourBranch
git fetch origin yourBranch:yourBranch
git checkout yourBranch

La stashligne enregistre les modifications que vous n'avez pas validées. La branchligne déplace votre branche vers un nom différent, libérant ainsi le nom d'origine. La fetchligne récupère la dernière copie de la télécommande. La checkoutligne recrée la branche d'origine en tant que branche de suivi.

Ou comme fonction bash:

replaceWithRemote() {
    yourBranch=${1:-`git rev-parse --abbrev-ref HEAD`}
    git stash
    git merge --abort
    git rebase --abort
    git branch -M ${yourBranch} replaced_${yourBranch}_`git rev-parse --short HEAD`
    git fetch origin ${yourBranch}:${yourBranch}
    git checkout ${yourBranch}
}

qui renomme la branche actuelle en quelque chose comme replace_master_98d258f.

Joshua S
la source
Peut vouloir inclure git stash popdans ce flux de travail. Si vous souhaitez réappliquer vos fichiers cachés.
eonist
Que faites-vous avec une branche cachée? J'ai peur que ça réapparaisse quelque part dans le futur bien après avoir oublié à quoi ça servait.
Scott Biggs
1
@ScottBiggs Si vous souhaitez supprimer la branche cachée, utilisez "git stash clear".
Mark A. Durham
5

Je suis un peu surpris que personne n'en ait encore parlé; Je l'utilise presque tous les jours:

git reset --hard @{u}

Fondamentalement, il @{u}s'agit simplement d'un raccourci pour la branche en amont que votre branche actuelle suit. Par exemple, cela équivaut généralement à origin/[my-current-branch-name]. C'est bien parce que c'est indépendant de la branche.

Assurez-vous d' git fetchabord d'obtenir la dernière copie de la branche distante.

TTT
la source
1
ça a l'air vraiment sympa, je me suis lassé de copier et coller le nom de la branche à réinitialiser!
pedroct92
1
J'ai eu quelques cas où j'ai ajouté des réponses à de vieilles questions, et mes réponses ont progressé dans le classement. J'espère que celui-ci le fera.
Jamie
3

Cela peut être fait de plusieurs façons, en continuant à modifier cette réponse pour diffuser une meilleure perspective de connaissances.

1) Réinitialiser dur

Si vous travaillez à partir de la branche de développement à distance, vous pouvez réinitialiser HEAD sur le dernier commit sur la branche à distance comme ci-dessous:

git reset --hard origin/develop

2) Supprimez la branche en cours et passez à nouveau à la caisse du référentiel distant

Considérant que vous travaillez sur le développement d'une branche dans le référentiel local, qui se synchronise avec la branche distante / développement, vous pouvez faire comme ci-dessous:

git branch -D develop
git checkout -b develop origin/develop

3) Annuler la fusion

Si vous êtes entre une mauvaise fusion (effectuée par erreur avec une mauvaise branche) et que vous souhaitez éviter la fusion pour revenir à la dernière branche comme ci-dessous:

git merge --abort

4) Abandonner le rebase

Si vous êtes entre une mauvaise rebase, vous pouvez abandonner la demande de rebase comme ci-dessous:

git rebase --abort
Amit Kaneria
la source
2

Vous pouvez faire comme @Hugo de @Laurent l'a dit, ou vous pouvez utiliser git rebasepour supprimer les commits que vous souhaitez supprimer, si vous savez lesquels. J'ai tendance à utiliser git rebase -i head~N(où N est un nombre, vous permettant de manipuler les derniers N commits) pour ce type d'opérations.

ksol
la source
En fait, c'est la commande 'git rebase' qui a tout gâché, puis des fusions forcées et des réinitialisations matérielles .. Quoi qu'il en soit, ce que je cherchais est juste un moyen facile de retirer l'ensemble du référentiel du serveur distant sans fusionner.
YemSalat
2

La réponse choisie est absolument correcte , mais elle ne m'a pas laissé les derniers commit / pushs ...

Donc pour moi:

git reset --hard dev/jobmanager-tools
git pull  ( did not work as git was not sure what branch i wanted)

Étant donné que je sais que je souhaite temporairement définir ma branche en amont pour quelques semaines sur une branche spécifique (la même que celle vers laquelle j'ai basculé / vérifié plus tôt et effectué une réinitialisation matérielle)

Donc , après la réinitialisation

git branch --set-upstream-to=origin/dev/jobmanager-tools
git pull
git status    ( says--> on branch  dev/jobmanager-tools 
Tom Stickel
la source
1

Si vous souhaitez mettre à jour une branche qui n'est pas actuellement extraite, vous pouvez faire:

git fetch -f origin rbranch:lbranch
kqr
la source
0

Comme prévu dans l'explication choisie, git reset est bon. Mais de nos jours, nous utilisons souvent des sous-modules: des référentiels à l'intérieur de référentiels. Par exemple, si vous utilisez ZF3 et jQuery dans votre projet, vous souhaitez très probablement qu'ils soient clonés à partir de leurs référentiels d'origine. Dans ce cas, la réinitialisation de git ne suffit pas. Nous devons mettre à jour les sous-modules vers cette version exacte définie dans notre référentiel:

git checkout master
git fetch origin master
git reset --hard origin/master
git pull

git submodule foreach git submodule update

git status

c'est la même chose que vous arriverez (cd) récursivement au répertoire de travail de chaque sous-module et exécuterez:

git submodule update

Et c'est très différent de

git checkout master
git pull

parce que les sous-modules pointent non pas sur une branche mais sur la validation.

Dans ce cas, lorsque vous extrayez manuellement une branche pour un ou plusieurs sous-modules, vous pouvez exécuter

git submodule foreach git pull
Eugene Kaurov
la source
Veuillez fournir une explication, en particulier lorsque vous répondez à des questions aussi anciennes. Votre réponse n'est pas utile telle quelle.
Erik A
La réponse acceptée propose déjà git reset --hard. Cela ajoute peu de valeur.
florisla
0
git reset --hard
git clean -fd

Cela a fonctionné pour moi - propre a également montré tous les fichiers supprimés. S'il vous indique que vous perdrez les modifications, vous devez vous cacher.

Travis Heeter
la source
-6

La façon la plus simple mais laide: supprimez votre dossier local et clonez à nouveau le référentiel distant.

Hugo
la source
10
Ou supprimez simplement la branche et réessayez.
laurent
Oui, je suppose que c'est ce que je vais faire si je ne trouve pas comment le faire de manière moins «laide»
YemSalat
2
Laid est parfois utile de savoir. Je souhaite que les gens ne réduisent pas les votes simplement parce qu'ils ne sont pas conventionnels: il doit y avoir une raison plus rationnelle de rétrograder ... et cela devrait être donné. Git est une chose qui donne des résultats. Ce n'est pas une sorte de texte sacré.
mike rodent
3
Je ne comprends pas les downvotes :-( Oui, c'est inélégant, etc. mais cela peut mieux fonctionner dans certains cas ... désolé @Hugo
silverdr
@Hugo, d'accord. Quelque chose de mystérieux et de malodorant est arrivé à ma branche de développement locale, et le chef d'équipe et le directeur de l'ingénierie ont suggéré, parmi des solutions plus élégantes, de simplement (compresser, copier et enregistrer mon travail de fonctionnalité, puis) ​​neutraliser le dépôt local et recloner.
AmitaiB