J'utilise Git subtree avec quelques projets sur lesquels je travaille, afin de partager du code de base entre eux. Le code de base est souvent mis à jour et les mises à niveau peuvent se produire dans n'importe lequel des projets, tous étant éventuellement mis à jour.
J'ai rencontré un problème où git signale que mon sous-arbre est à jour, mais le push est rejeté. Par exemple:
#! git subtree pull --prefix=public/shared project-shared master
From github.com:****
* branch master -> FETCH_HEAD
Already up-to-date.
Si je pousse, je devrais recevoir un message disant qu'il n'y a rien à pousser ... Non? DROITE? :(
#! git subtree push --prefix=public/shared project-shared master
git push using: project-shared master
To [email protected]:***
! [rejected] 72a6157733c4e0bf22f72b443e4ad3be0bc555ce -> master (non-fast-forward)
error: failed to push some refs to '[email protected]:***'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Quelle pourrait être la raison de cela? Pourquoi pousser échoue-t-il?
git
git-subtree
Mateusz
la source
la source
--rejoin
pour accélérer les poussées de sous-arbres. Lorsque je parcours manuellement le push de sous-arborescence, en cours d'exécutionsubtree split --rejoin
, la branche de sous-arborescence fractionnée n'a que l'historique de la dernière rejointe, alors qu'elle contient normalement l'historique complet du sous-arbre. Pour moi, c'est la cause immédiate d'une erreur non accélérée. Je ne sais toujours pas pourquoi la division des sous-arbres génère un historique tronqué.Réponses:
J'ai trouvé la réponse sur ce commentaire de blog https://coderwall.com/p/ssxp5q
la source
error: unknown option 'prefix'
heroku
etpythonapp
avoir dans la réponse. Traduire ceci hors d'une langue spécifique à Heroku:git push <your subtree's origin> `git subtree split --prefix=Path/to/subtree master`:master --force
Sous Windows, la commande imbriquée ne fonctionne pas:
Vous pouvez simplement exécuter le bit imbriqué en premier:
Cela renverra (après beaucoup de nombres) un jeton, par exemple
Utilisez ceci dans la commande contenant, par exemple:
la source
git subtree
une commande avant. Après avoir utilisé votre solution, j'ai pu déployer un dossier sur heroku au lieu de tout monUtilisez le
--onto
drapeau:[EDIT:
subtree push
ne transmet malheureusement pas--onto
au sous-jacentsplit
, donc l'opération doit être effectuée en deux commandes! Cela fait, je vois que mes commandes sont identiques à celles de l'une des autres réponses, mais l'explication est différente, je vais donc la laisser ici de toute façon.]Ou si vous n'utilisez pas bash:
J'ai passé des heures à parcourir la source git-subtree pour comprendre celle-ci, alors j'espère que vous l'apprécierez;)
subtree push
commence par s'exécutersubtree split
, ce qui réécrit votre historique de validation dans un format qui devrait être prêt à être envoyé. Pour ce faire, ilpublic/shared/
supprime le devant de tout chemin qui le contient et supprime toute information sur les fichiers qui ne l'ont pas. Cela signifie que même si vous tirez non-écrasé, tous les commits de sous-référentiel en amont sont ignorés car ils nomment les fichiers par leurs chemins nus. (Commits qui ne touchent aucun fichier souspublic/shared/
, ou les commits de fusion identiques à un parent, sont également réduits. [EDIT: De plus, j'ai depuis trouvé une détection de squash, donc maintenant je pense que ce n'est que si vous avez tiré non écrasé, puis la fusion simpliste de la validation décrite dans une autre réponse parvient à choisir le chemin non écrasé et ignorer le chemin écrasé.]) Le résultat est que le contenu qu'il tente de pousser finit par contenir tout travail commis par une personne dans le référentiel hôte actuel à partir duquel vous poussez, mais pas les personnes engagées directement dans le sous-référentiel ou via un autre hôte dépôt.Cependant, si vous utilisez
--onto
, tous les commits en amont sont enregistrés comme OK pour être utilisés textuellement, donc lorsque le processus de réécriture les trouve comme l'un des parents d'une fusion, il veut les réécrire, il les conservera au lieu d'essayer de les réécrire. de la manière habituelle.la source
git remote -v
.--onto
option aide git à identifier les commits qui sont déjà dans le sous-référentiel.Pour une application de type "pages GitHub", où vous déployez une sous-arborescence "dist" dans une branche gh-pages, la solution peut ressembler à ceci
Je mentionne cela car il semble légèrement différent des exemples d'heroku donnés ci-dessus. Vous pouvez voir que mon dossier "dist" existe sur la branche master de mon repo, puis je le pousse comme sous-arborescence vers la branche gh-pages qui est également à l'origine.
la source
J'ai également rencontré ce problème auparavant, et voici comment je l'ai résolu.
Ce que j'ai découvert, c'est que j'avais une branche qui n'était pas rattachée à la branche principale locale. Cette branche existe et elle est juste suspendue dans le vide. Dans votre cas, c'est probablement appelé
project-shared
. En supposant que c'est le cas et lorsque vous faites un,git branch
vous pouvez voir uneproject-shared
branche locale , alors vous pouvez `` ajouter '' de nouveaux commits à votreproject-shared
branche existante en faisant:git subtree split --prefix=public/shared --onto public-shared --branch public-shared
La façon dont j'ai compris est de
git subtree
commencer à créer une nouvelle branche--onto
, dans ce cas, c'est lapublic-shared
branche locale . Ensuite, la branche signifie créer une branche, qui remplace simplement l'anciennepublic-shared
branche.Cela conservera tous les SHA précédents de la
public-shared
branche. Enfin, vous pouvez faire ungit push project-shared project-shared:master
En supposant que vous ayez également une
project-shared
télécommande; cela poussera le local suspendu dans laproject-shared
branche vide vers lamaster
branche de la télécommandeproject-shared
.la source
Ceci est dû à la limitation de l'algorithme d'origine. Lors de la gestion des merge-commits, l'algorithme d'origine utilise un critère simplifié pour couper les parents non liés. En particulier, il vérifie s'il existe un parent qui a le même arbre. Si un tel parent était trouvé, il réduirait le commit de fusion et utiliserait le commit parent à la place, en supposant que d'autres parents ont des changements sans rapport avec le sous-arbre. Dans certains cas, cela entraînerait la suppression de certaines parties de l'historique, ce qui entraîne des modifications réelles du sous-arbre. En particulier, il supprimerait des séquences de commits, qui toucheraient un sous-arbre, mais aboutiraient à la même valeur de sous-arbre.
Voyons un exemple (que vous pouvez facilement reproduire) pour mieux comprendre comment cela fonctionne. Considérez l'historique suivant (le format de ligne est: commit [tree] subject):
Dans cet exemple, nous nous séparons
dir
. CommitsD
etE
ont le même arbrez
, parce que nous avons commitC
, qui a annulé le commitB
, donc laB-C
séquence ne fait rien pourdir
même si elle a des modifications.Maintenant, faisons le fractionnement. D'abord, nous nous sommes séparés sur commit
C
.Ensuite, nous nous sommes séparés sur commit
E
.Oui, nous avons perdu deux commits. Cela entraîne une erreur lors de la tentative de pousser le deuxième fractionnement, car il n'a pas ces deux validations, qui sont déjà entrées dans l'origine.
Habituellement, vous pouvez tolérer cette erreur en utilisant
push --force
, car les commits supprimés ne contiennent généralement pas d'informations critiques. À long terme, le bogue doit être corrigé, de sorte que l'historique de fractionnement aurait en fait tous les commits, qui se touchentdir
, comme prévu. Je m'attendrais à ce que le correctif inclue une analyse plus approfondie des commits parent pour les dépendances cachées.Pour référence, voici la partie du code d'origine, responsable du comportement.
la source
La réponse d'Eric Woodruff ne m'a pas aidé, mais ce qui suit l'a fait:
J'ai l'habitude de «git subtree pull» avec l'option «--squash». Il semble que cela a rendu les choses plus difficiles à réconcilier, donc j'ai dû faire une extraction de sous-arbre sans écraser cette fois, résoudre certains conflits, puis pousser.
Je dois ajouter que la traction écrasée n'a révélé aucun conflit, m'a dit que tout allait bien.
la source
Une autre solution [plus simple] est d'avancer la tête de la télécommande en faisant un autre commit si vous le pouvez. Après avoir tiré cette tête avancée dans le sous-arbre local, vous pourrez à nouveau y pousser.
la source
Vous pouvez forcer le transfert des modifications locales vers le dépôt de sous-arborescence distant
la source
Un PowerShell rapide pour les utilisateurs de Windows basé sur la solution de Chris Jordan
la source
C'est donc ce que j'ai écrit sur la base de ce que @entheh a dit.
la source
Eu ce problème, aussi. Voici ce que j'ai fait, en fonction des principales réponses:
Donné:
Entrez ceci:
Notez que le jeton qui est généré par 'git subtree push' est utilisé dans 'git push'.
la source