2012-09-26 2 views
4

Dans ma branche principale, j'ai 2 fichiers:Fusion d'une branche avec fichier supprimé Retour à la racine

file1.txt 
file2.txt 

J'ai créé une nouvelle branche nommée b1 à partir de là. En b1, j'ai modifié file2.txt, et supprimé accidentellement file1.txt (à partir du disque, lorsque j'ouvre Windows Explorer dans le dossier source, file1.txt n'est pas là). Maintenant, je veux garder les changements dans file2.txt et récupérer file1.txt de master (je n'ai pas besoin de la version supprimée). Je suis passé au master, j'ai fusionné avec b1, aucun conflit n'est arrivé, il a dit 'tout à jour' mais file1.txt n'est pas là. Qu'est-ce que je devrais avoir fait?

Répondre

11

Je pense qu'il ya plusieurs questions que vous posez ici. Le premier semble être "Comment puis-je récupérer file1.txt?" En supposant que votre graphique de révision ressemble à ceci:

   M 
(master) o -- o --- o ------o HEAD 
       \   /
(b1)    o -- o -- o 
       A B C 

Vous pouvez obtenir la copie précédente de file1.txt via git checkout:

git checkout HEAD~1 -- file1.txt 

Ce ressuscitera file1.txt et scène dans votre copie de travail. Vous pouvez le git commit et le fichier sera de retour. Remarque: HEAD~1 dit prendre le premier parent de HEAD, qui pointe vers l'état de maître avant de fusionner b1. Si vous connaissez l'identifiant de validation, vous pouvez l'utiliser à la place de HEAD~1.

L'autre question que vous semblez poser est "Qu'est-ce que je devrais avoir fait dans la branche b1 pour éviter cela?" Le choix le plus évident aurait été de ne pas supprimer file1.txt en premier lieu. Mais supposons que vous pensiez que vous deviez, et a décidé que le choix était mauvais. Ensuite, supposons que vous n'avez pas partagé la branche b1 en poussant les changements quelque part. Si vous avez remarqué que vous avez supprimé le fichier tout de suite, vous pouvez faire:

git checkout HEAD~1 -- file1.txt 
git commit --amend 

qui dirait, « me rendre file1.txt, puis fusionner ce fichier dans la dernière validation. » Cela a l'effet d'apparaître comme si vous n'aviez jamais supprimé le fichier en premier lieu.

Si vous n'avez pas remarqué que le fichier a été supprimé immédiatement et que vous avez plusieurs validations intermédiaires, vous pouvez utiliser git rebase pour résoudre le problème.

Si vous avez supprimé le fichier dans son propre commit, vous pouvez utiliser git rebase -i pour supprimer le commit de l'historique de la branche. Supposons que B était le commit qui a supprimé le fichier, et c'est la seule chose faite dans ce commit. Alors que sur b1, vous voulez exécuter quelque chose comme:

git rebase -i B~1 

Supprimez la ligne qui contient l'infraction commit (B), sauvegarder et quitter. Votre branche vient de réécrire son historique sans B. Par exemple, je courais git rebase -i et cela a été montré dans l'éditeur:

pick 40f76a7 removed bar 
pick 30a25f5 modified foo 

je puis abandonné 40f76a7 de la liste, puis m'a laissé:

pick 30a25f5 modified foo 

L'histoire ressemble maintenant à ceci après la fusion :

   M 
(master) o -- o --- o ------o HEAD 
       \   /
(b1)    o ------- o 
       A   C' 

Notez le commit id de C' est différent de C parce B plus existe, et les parents sha1 font partie de l'ID de validation. IOW, le sha1 de C a changé parce que nous avons réécrit l'histoire.

Si vous avez supprimé file1.txt et que vous avez enregistré un tas d'autres modifications dans le même commit, il y a quelques étapes supplémentaires. Tout d'abord, ramener le dossier et l'engager:

git checkout B~1 -- file1.txt 
git commit -m "Reinstate file1.txt" 

Appelons le nouveau commit D. Notre graphique de révision ressemble maintenant à

   M 
(master) o -- o --- o -----------o HEAD 
       \   
(b1)    o -- o -- o -- o 
       A B C D 

Maintenant, faites:

git rebase -i B~1 

Et déplacer la ligne contenant commit id D à engager juste après id B, et changer pick à squash. Par exemple, je reçois ce git rebase -i B~1 lors de l'exécution:

pick 40f76a7 removed bar plus other changes 
pick 30a25f5 modified foo 
pick 6177cb7 add bar 

6177cb7 est le commettras que la barre rétablit. Je propose donc juste en dessous 40f76a7 et changer la commande à squash:

pick 40f76a7 removed bar plus other changes 
squash 6177cb7 fix bar 
pick 30a25f5 modified foo 

Enregistrer et quitter. Il vous demandera de réparer le message de validation. Fais ça. Lorsque vous aurez terminé, vous vous retrouvez avec une histoire qui ressemble à ceci:

   M 
(master) o -- o --- o -----------o HEAD 
       \   
(b1)    o -- o -- o 
       A B' C' 

Le nouveau B' ne supprime plus file1.txt. À ce stade, vous êtes prêt à fusionner avec le maître.

Quelques remarques de clôture. Soyez prudent avec git rebase. Vous pouvez perdre l'histoire, si vous ne faites pas attention. Assurez-vous de lire la page de manuel git rebase.Il y a beaucoup d'informations utiles là-bas. Note: tout ce travail avec git rebase est seulement nécessaire si vous voulez supprimer le fait que vous avez supprimé le fichier de l'historique. Si vous êtes d'accord avec un commit montrant que vous ramenez le fichier, alors utilisez le git checkout pour restaurer le fichier et le valider. C'est beaucoup moins fastidieux et plus facile pour un nouvel utilisateur git. git rebase est assez avancé, et prend un peu de pratique. Cependant, si vous investissez le temps et l'apprenez bien, c'est vraiment très utile.

+0

génial, très instructif –

3

La fusion n'est pas quelque chose que vous faites dans ce cas, il est normal que Git conserve la suppression lors de la fusion au maître. Si vous voulez obtenir un fichier d'une autre branche ou d'un autre tag, il s'agit du git checkout master -- filename.

Dans votre cas, vous devez annuler la fusion avant:

  1. assurez-vous que vous êtes sur le maître, et que votre répertoire de travail est propre (git status montre pas de changement)
  2. annuler la fusion vous avez fait

    git reset --hard [email protected]{1} 
    
  3. Retournons à b1

    git checkout b1 
    
  4. caisse file1.txt de maître dans votre copie de travail:

    git checkout master -- file1.txt 
    
  5. commettras ou modifier votre engagement précédent, ou tout ce que vous voulez faire
+0

cool, a travaillé pour moi! –

Questions connexes