2011-01-15 8 views
8

Sto cercando di mantenere una copia nuda di un repository Git e di avere alcuni problemi nel mantenere aggiornati i rami di monitoraggio remoto. Creo i rami di monitoraggio remoti, come questa:Come posso ottenere un ramo di monitoraggio remoto per rimanere aggiornato con origini remote in un repository Git spoglio?

git branch -t 0.1 origin/0.1 

Questo sembra fare quello che devo fare per quel punto nel tempo. Tuttavia, se apporto le modifiche a origin e poi recupero con il repository nudo, le cose iniziano a cadere a pezzi. Il mio flusso di lavoro è simile al seguente:

git fetch origin 

Sembra che tutti i commit vengono in a quel punto, ma la mia copia locale del 0.1 non è in fase di aggiornamento. Vedo che le modifiche sono state introdotte nel repository facendo quanto segue:

git diff 0.1 refs/remotes/origin/0.1 

Che cosa devo fare per ottenere la mia filiale di monitoraggio aggiornato con gli aggiornamenti del telecomando? Mi sento come se dovessi perdere un gradino o una bandiera da qualche parte.

Aggiornato: ulteriore chiarimento

Normalmente si spinge in un repository nuda, piuttosto che correre git fetch dal suo interno. Se riesci a farlo, la vita sarà molto più facile.

Ecco un po 'di chiarimenti sul flusso di lavoro.

Il repository git pubblico del progetto è ospitato su GitHub. Sto gestendo il progetto (wiki, problemi, forum) usando Redmine. Redmine richiede un repository locale per funzionare. Quando GitHub riceve modifiche, ping re Redmine. Redmine tenta quindi di recuperare le modifiche dalla sua origine (GitHub).

Questo funziona perfettamente se sto solo lavorando con il master ma non funzionava con i miei rami di monitoraggio. Le modifiche venivano importate ma non venivano elencate nel ramo nel browser del repository Redmine perché i rami locali non venivano aggiornati.

Sono sicuro che avrei potuto risolvere questo problema in un altro modo, ma trovare una soluzione (generica) per far funzionare i rami di tracciamento era decisamente la mia preferenza in quanto la maggior parte dei plugin relativi a git per Redmine si basa su cose come "git fetch origine "è tutto ciò che deve essere fatto.

Vedere la risposta accettata per la soluzione completa. La soluzione --mirror sembra essere esattamente ciò che è necessario in questo caso.

risposta

17

Normalmente uno spingerebbe in un repository nudo, piuttosto che eseguire git fetch all'interno di esso. Se riesci a farlo, la vita sarà molto più facile.

Se si dispone di per recuperare anziché premere, e si desidera creare un mirror di origine nel repository nudo, è possibile evitare di avere rami di rilevamento remoto interamente. Se stai iniziando questo mirror da zero, tieni presente che git farà tutto questo setup per te se inizialmente cloni il repository con git clone --mirror.

In caso contrario, si potrebbe ottenere un effetto simile con:

git fetch origin +refs/heads/*:refs/heads/* 

Il + significa che questo sovrascriverà lo stato delle sedi locali con quelli dal telecomando. Senza lo +, gli aggiornamenti che non sono una fusione rapida verranno rifiutati. Tuttavia, se questo è solo uno specchio, non dovrebbe importare. (È possibile configurare questo per essere l'azione predefinita su git fetch origin impostando la variabile di configurazione remote.origin.fetch-+refs/heads/*:refs/heads/*. Se si desidera eseguire il mirroring tag e rami a distanza di tracciamento di origine, nonché, si potrebbe usare +refs/*:refs/* invece.)

Tuttavia, se, come inizialmente richiesto, si desidera mantenere i rami di rilevamento remoto e unirli in modo selettivo in rami locali, è possibile utilizzare i seguenti passaggi, ma non li consiglio necessariamente a meno che non si sia l'unica persona che utilizza questo repository nudo. (Nota: originariamente qui ho suggerito di usare "git symbolic-ref HEAD ref/heads/whatever" per cambiare ramo e "git reset --soft" per cambiare il ramo ref - tuttavia, Charles Bailey ha sottolineato nei commenti che si può usa "git update-ref refs/heads/any refs/remotes/origin/whatever", che non richiede di cambiare prima.)

In primo luogo, si potrebbe voler controllare che l'aggiornamento del ramo abbia è stata una fusione veloce, e dopo l'aggiornamento il ramo. Nota che c'è una condizione di competizione qui, ed è per questo che dico che dovresti farlo solo se sei l'unica persona che usa il tuo repository locale - il controllo sarebbe inutile se qualcun altro si muove sul ramo tra quei passaggi.

  1. È possibile verificare che un merge equivalente sarebbe un fast-forward (vale a dire che la storia della origin/master comprende master) confrontando git merge-base master origin/master con git show-ref master - dovrebbero essere gli stessi. Oppure si potrebbe utilizzare lo script is-ancestor in this question, che fa quei comandi con alcuni ulteriori controlli.)
  2. Infine, è possibile aggiornare il ramo corrente (master in questo caso) per puntare a origin/master con git update-ref refs/heads/master refs/remotes/origin/master

Tuttavia , come ho detto all'inizio, immagino che la vera soluzione che si desidera o è:

  • Spingendo nel repository nudo invece o
  • mirroring del Reposi remota nuda esattamente come ho descritto sopra

Spero che sia di qualche utilità.

+1

'git merge' richiede sempre un albero di lavoro, devi usare' git update-ref' invece in un repository nudo.Penso che tu abbia ragione nel dire che uno specchio suona come una soluzione migliore. Potrebbe valere la pena aggiungere un non su 'git clone --mirror'. –

+0

@Charles Bailey: la ragione per cui ho pensato che potesse essere un bug è che nella sorgente di builtin-merge.c c'è un commento che inizia "A questo punto, abbiamo bisogno di una vera fusione ..." dopo il punto in cui un fast- in avanti sarebbe stato fatto - non credo che l'indice o l'albero di lavoro siano necessari fino a quel momento. Comunque rimuoverò quell'osservazione. –

+0

Si potrebbe chiedere sulla mailing list git, ma non sono convinto che sarebbe considerato un bug. Penso che, in generale, sia più coerente avere una chiara distinzione tra i comandi che non richiedono un albero di lavoro e quelli che lo fanno. Avere un comando che ha bisogno di un albero di lavoro è un'interfaccia più complessa che potrebbe causare qualche malinteso. –

1

Quando si modifica fetch, le modifiche remote stanno aggiornando il proprio riferimento locale per il telecomando, origin/0.1 (ciò non causa mai alcun conflitto, poiché origin/0.1 non ospita mai alcuna modifica locale). Per importare tali modifiche, è possibile da 0.1, in modo che il ramo HEAD (0.1) punti allo stesso commit del ramo remoto.

Si noti che così facendo si perderanno le modifiche a 0.1 non provenienti dal telecomando.

+1

Se ho capito bene la domanda, non funzionerà, dato che la domanda si interroga su un repository nudo e su 'git merge' e' git pull' richiedono un albero funzionante. –

+0

Oh, hai ragione! Ho modificato la mia risposta di conseguenza. – huitseeker