Perché non eseguire modifiche irrisolte?


15

In un VCS tradizionale, posso capire perché non dovresti commettere file non risolti perché potresti rompere la build. Tuttavia, non capisco perché non dovresti eseguire il commit di file non risolti in un DVCS (alcuni di essi ti impediranno effettivamente di eseguire il commit dei file).

Invece, penso che il tuo repository dovrebbe essere bloccato dallo spingere e tirare , ma non impegnarti.

Essere in grado di impegnarsi durante il processo di fusione ha diversi vantaggi (come lo vedo io):

  • Le modifiche effettive all'unione sono nella cronologia.
  • Se l'unione era molto ampia, è possibile effettuare commit periodici.
  • Se hai commesso un errore, sarebbe molto più semplice ripristinare (senza dover ripetere l'intera unione).
  • I file possono rimanere contrassegnati come non risolti fino a quando non vengono contrassegnati come risolti. Ciò impedirebbe di spingere / tirare.

Potresti anche potenzialmente avere un set di changeset che agiscono come unione anziché solo uno. Ciò ti consentirebbe di utilizzare ancora strumenti come git rerere.

Quindi perché l'impegno con i file non risolti non è visto / prevenuto? C'è qualche motivo diverso dalla tradizione?


1
Da chi è malvisto o prevenuto?
pdr,

@pdr Alcuni sviluppatori con cui ho lavorato si sono accigliati. Almeno hg 1.6dopo un'unione, i file sono contrassegnati come non risolti. hgsarà non lasciare che si impegnano fino a quando non li hai contrassegnato come risolto (non significa necessariamente che in realtà si deve risolverli, ma presumo che è l'idea).
Esplosione di pillole

1
Quindi, per "file non risolti", intendi davvero "fusioni non risolte"?
pdr,

@pdr no, hgmantiene effettivamente un elenco di file che sono stati o non sono stati contrassegnati come "risolti" (usando hg resolve). Se ci sono Ufile in questo elenco, non ti permetterà di impegnarti.
Pillole di esplosione

1
hg resolveè utilizzato specificamente per le fusioni con conflitti; vedi selenic.com/mercurial/hg.1.html#resolve . Note that Mercurial will not let you commit files with unresolved merge conflicts. You must use hg resolve -m ... before you can commit after a conflicting merge.
Mike Partridge,

Risposte:


6

Il problema più grande che posso vedere è che crea una finestra di commit in cui le cose sono unite a metà e (probabilmente) non funzionano correttamente. Quando si spinge il set finale di commit locali, tutti questi commit intermedi appariranno anche per tutti gli altri. Nel mondo ideale, dovrei essere in grado di eseguire qualsiasi commit e il codice dovrebbe funzionare. Se inizi a eseguire il commit nel mezzo di fusioni, lo stato del codice non è ben definito.

Una cosa che potresti fare è fare commit locali nella tua unione, e poi raggrupparli in un grande commit quando spingi (anche se non sono sicuro di come (se?) Qualsiasi vcs lo supporta). Anche se questo potrebbe comportare alcuni dei vantaggi che hai citato, non sono sicuro che valga la pena complessità extra (abbiamo già a che fare con un'area abbastanza confusa e complessa).


5
Non so che sono d'accordo con la capacità di eseguire qualsiasi commit e farlo funzionare. Gran parte del punto di impegnarsi in un DVCS è impegnare i tuoi progressi , quindi le cose sono destinate a essere interrotte o incomplete per la maggior parte del tempo .
Pillole di esplosione

2
Avere sempre impegni di lavoro ha dei bei benefici. Ad esempio, se stai cercando di rintracciare quando è stato introdotto un bug, è utile essere in grado di attraversare la cronologia per vedere quando qualcosa si è rotto (vcs ha anche comandi per eseguire ricerche binarie sulla cronologia). Se non hai impegni di lavoro, non sarai in grado di rintracciare i bug nel modo più efficace.
Oleksi,

1
Git supporta commit in bundle.
deltree

3

Conosco molto bene Git, quindi risponderò per quella prospettiva.

Non vedo un motivo per cui tu o qualsiasi altro VCS vorreste consentire il commit di un file non unito, in particolare se fosse un codice. Devi mantenere il repository in uno stato coerente e ciò che stai suggerendo violerebbe l'atomicità del commit. Molti VCS cambiano fisicamente il file per mostrare dove si trovano i conflitti: Git, SVN e CVS usano gli indicatori di tipo >>>> <<<<. In un VCS con commit e fusioni a livello di repository atomico, avresti semplicemente creato un nodo che non ha senso per nessuno tranne te. Nello sviluppo del software, il tuo progetto non è stato realizzato. Nel documento di un gruppo, nessuno sa quali modifiche sono corrette.

Ora, Git fornisce alcuni strumenti che potrebbero facilitare questo, se il tipo di commit che suggerisci fosse consentito. Ad esempio, potresti schiacciare tutti i commit di unione prima di premere. Questo finisce per essere lo stesso di un tipico commit di unione.

Preoccupazioni specifiche sull'elenco dei vantaggi:

  1. Le modifiche effettive all'unione sono nella cronologia. Perché hai bisogno di informazioni extra? I DVCS sono molto bravi a limitare i conflitti in aree ristrette. Dopo aver scelto il changeset da conservare, il confronto tra la copia del nodo di commit merge e la copia precedente ti darà esattamente questo.
  2. Se l'unione era molto ampia, è possibile effettuare commit periodici. Questa è una preoccupazione valida, ma non dovresti mai arrivare qui in primo luogo. Le filiali dovrebbero costantemente attirare cambiamenti a monte, in modo che ciò non accada mai. Anche strumenti come il rebasepicking di una ciliegia alla volta possono aiutarti in alcune situazioni.
  3. Se hai commesso un errore, sarebbe molto più semplice ripristinare (senza dover ripetere l'intera unione). Vedi sopra - i tuoi conflitti non dovrebbero diventare così ingestibili.

L'unico modo in cui questo suggerimento potrebbe funzionare è se il ramo fosse se l'intera unione fosse atomica: potresti vedere una serie di commit, ma sarebbero solo passaggi in un commit di unione più grande che dovrebbe essere trattato come un nodo nella struttura di commit . Non credo che nessun VCS attuale abbia supporto per questo tipo di flusso di lavoro e non credo sia necessario.


I conflitti probabilmente non dovrebbero diventare così ingestibili, ma spesso lo sono (almeno nella mia esperienza). Penso che l'intera unione dovrebbe essere atomica; questo è quello che sto suggerendo. Potrebbe non essere necessario, mi sto solo chiedendo perché non è stato fatto. Inoltre, non puoi necessariamente scegliere l'una o l'altra opzione in un conflitto; a volte è una combinazione di entrambi i cambiamenti. Questo è particolarmente confuso.
Pillole di esplosione

"Devi mantenere il repository in uno stato coerente". Non penso sia vero. Un repository locale è uno spazio di lavoro , non un santuario. Se aiuta a impegnarsi nel bel mezzo di un'unione, fallo IMHO. Se lo fai perché non conosci meglio, suggerirei di non farlo. Se sei un programmatore esperto, tuttavia, dovresti fare tutto ciò che funziona meglio per te. Non essere dogmatico nel mantenere incontaminato il tuo repository locale.
Bryan Oakley,

1

La mia esperienza principale risiede con Mercurial, anche se uso sporadicamente anche git.

Mercurial non ti impedisce di eseguire il commit di file non risolti, ti scoraggia . Stesso affare con la spinta prima di tirare cambiamenti che non hai.

Tutto ciò che devi fare in Mercurial è, una volta che hai i file nel modo in cui li vuoi impegnare:

hg resolve --mark --all
hg commit -m "I'm such a rebel"

--mark contrassegna ... i file come risolti senza richiedere all'utente lo strumento di unione. --all si occuperà di selezionare tutti i file contrassegnati da conflitti.

Se vuoi spingere senza tirare (e di conseguenza dover unire i cambiamenti degli altri) fai come un Jedi :

hg push --force

Il prossimo che tira otterrà +1 testa (nessun gioco di parole previsto)

Sono sicuro che c'è un modo per fare le stesse cose con Git (anche se probabilmente è più contorto).


1

Quando mi unisco a git, commetto immediatamente tutte le modifiche (inclusi i conflitti di unione). Quindi, nei miei prossimi commit, risolvo i conflitti di unione tramite un editor di testo. Dopo che i conflitti sono stati risolti, spingo, se desiderato.

Onestamente non capisco perché gli altri non lo fanno in questo modo, o git non lo impone.

  • Il "merge commit" è ora una chiara storia di ciò che doveva essere unito.
  • I seguenti commit mostrano esattamente cosa hai fatto per risolvere i conflitti di unione.
  • Quando si preme, i conflitti vengono risolti e la build ininterrotta sulla punta del ramo.
  • In qualsiasi momento, se rovini la risoluzione dei conflitti, puoi semplicemente tornare a uno dei commit "post unione" e riprovare.

Un enorme svantaggio del flusso di lavoro standard di risoluzione dei conflitti prima del commit è che le modifiche alla tua copia locale possono insinuarsi. Le aggiunte sono nascoste dalla revisione del codice dall'enorme differenza di unione, quindi non noti che hai commesso accidentalmente un'API chiave o ecc.

Il mio flusso di lavoro sopra descritto evita questo problema di copia locale e consente anche ai revisori del codice di esaminare (solo) i dettagli della risoluzione di unione in una differenza di commit che assomiglia esattamente a una differenza di commit standard.


0

Penso che sia meglio spingere piccoli cambiamenti e spingere spesso, quando è possibile (e ovviamente non è sempre), e non commettere codice che non si costruisce o è completo a metà (tutti commettiamo errori, ma don non farlo apposta). Vengo anche da Git, e una delle cose migliori che penso è il fatto che puoi avere una copia praticabile del repository sul desktop ... che puoi quindi modificare in base al tuo cuore. Quando i tuoi grandi cambiamenti sono stati fatti, mandali via.

Fare un sacco di open source con git la frustrazione più grande per me è stato ottenere il codice mezzo fatto cadere nel repository, e provare a fare un build, ma non ci riuscì, perché il ragazzo ha fatto metà del lavoro e ha detto "Sono occupato ora , Lo finirò tra una settimana ". Quindi finirei per scartarlo (il che infastidirebbe il ragazzo), o prenderei il tempo per finire e integrarlo completamente.

Immagino dal mio punto di vista, tenere localmente le cose a metà culo, inviare le cose buone via cavo.


0

Non essere schiavo dei tuoi strumenti.

L'obiettivo di un VCS è di permetterti di fare il tuo lavoro. Il tuo compito non è quello di mantenere un repository locale incontaminato, il tuo compito è quello di scrivere codice. Se impegnarti presto e spesso a livello locale ti consente di lavorare meglio, fallo.

Tuttavia, non dovresti spingere a monte il codice non funzionante.


0

Perché fondamentalmente è una cattiva idea - ti condurrà a un repository che si trova in uno stato di insensibilità (e la sua eruzione cutanea presuppone che tu possa mai spingere ovunque, anche se si potrebbe sostenere che dovresti sempre avere almeno una copia).

Vedo che nel caso di una fusione grande / complessa potresti voler salvare il tuo lavoro in corso e stabilire un punto di riferimento ma lasceresti comunque il sistema in uno stato incasinato che deve essere risolto.

E ci sono alternative - hai la possibilità di unirti prima della testa - che potrebbero darti la possibilità di adattarti ai cambiamenti senza fusioni epiche (o almeno con fusioni più grandi che sono più facili da comprendere).

Questo è il caso in cui trovo che il rebase di git sia particolarmente utile (soggetto alle consuete avvertenze sul rebasing) perché stai riproducendo le tue modifiche in cima allo stato attuale in cui puoi correggere i conflitti in pezzi più piccoli.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.