2014-09-29 10 views
11

Molte lune fa ho aggiunto una sottostruttura al mio repository git. Questa sottostruttura comprendeva diverse cartelle e file. Ho aggiunto la sottostruttura invece di creare un sottomodulo (come raccomandato). Ora capisco che voglio solo uno dei file nella sottostruttura e niente del resto. Ancora peggio, quando altri clone mio repository, ciò che ottengono non è ciò che è previsto, c'è qualche conflitto con la sottostruttura e l'altro codice che ho creato.Come rimuovere la sottostruttura di git precedentemente aggiunta e la sua cronologia

posso ottenere cavalcata dei file/cartelle con

git rm subtree–folder1 subtree_folder2 subtree_files.* 

tuttavia, sono ancora a sinistra con una storia lunga commettere Dalla sottostruttura.

Ho eseguito una discreta quantità di sviluppo da quando ho aggiunto la sottostruttura e non posso perdere la cronologia dei commit che ho generato.

In breve questo è quello che vorrei:

  1. Rimuovere tutti i file sottostruttura/cartelle.
  2. Dimentica la cronologia di tutti gli elementi della sottostruttura.
  3. Rimasto solo con il mio codice e la mia cronologia.

È possibile?

PS. Una possibile complicazione è che ho spostato il singolo file di intestazione che volevo conservare dalla sottostruttura in qualche cartella del mio codice. Spero che questo non mi impedisca di dimenticare la storia del sottotenoso.

Un tentativo

Dopo un checkout fresco dal server remoto Ho il seguente:

$ ls 
.git    CMakeLists.txt Read.cpp   logging.conf 
.gitignore  ENDF6   TestData   src 
.sparse-checkout LICENCE   doc    test 
.travis.yml  README.md  include   tools 

Dove .gitignore ha solo: build/ debug/

quando provo il comando come suggerito non ho una risposta molto felice:

$ git filter-branch --index-filter 'git rm --cached -rf test tools src doc LICENCE README.md .travis.yml' HEAD 
Rewrite 2fec85e41e40ae18efd1b130f55b14166a422c7f (1/1701)fatal: pathspec 'test' did not match any files 
index filter failed: git rm --cached -rf test tools src doc LICENCE README.md .travis.yml 

Non so perché dice che ha un problema con test quando è chiaramente lì. Sono sconcertato.

+0

Hai provato semplicemente a utilizzare 'git rm ' per rimuovere la sottostruttura? –

+0

@hunch_hunch L'ho fatto così come i comandi qui: http://stackoverflow.com/questions/15890047/how-to-remove-history-of-deleted-git-subtree-folder ma ho ancora tutta la storia di il sottoalbero Aiuto! – jlconlin

+0

Stai per riscrivere la cronologia del tuo repository tramite rebase o filter-branch? –

risposta

15

È necessario usa un filtro-ramo insieme con l'opzione --prune-empty per rimuovere qualsiasi commit che non introduce più nuove modifiche.

git filter-branch --index-filter 'git rm --cached --ignore-unmatch -rf dir1 dir2 dirN file1 file2 fileN' --prune-empty -f HEAD 

Dopo di che, se si vuole recuperare spazio su disco è necessario eliminare tutti gli arbitri originali che ramo filtro salvato, scadono il reflog, e la spazzatura raccogliere.

+0

Grazie per il tuo aiuto! Non è mostrato qui, ma nella nostra chat @AndrewC ha fornito la risposta necessaria. – jlconlin

+0

git log mostra ancora la cronologia. Forse mi manca qualcosa ... –

+0

@SkylarSaveland Vedi la [chat] (http://chat.stackoverflow.com/rooms/62556/discussion-between-jeremy-and-andrew-c) jlconlin si riferisce, anche se dovrebbe essere qui la soluzione. mm – Llopis

2

È possibile utilizzare git filter-branch per applicare un'operazione a tutti i commit effettuati in un ramo. Ciò include l'eliminazione di file da ciascun commit mentre si riscrive l'intera cronologia. Una buona descrizione e le istruzioni sono disponibili qui: http://gitready.com/beginner/2009/03/06/ignoring-doesnt-remove-a-file.html. Puoi trovare utile anche la seguente domanda: Completely remove files from Git repo and remote on GitHub (è dove ho trovato il link). Il comando effettivo che verrà eseguito con questa soluzione sarà qualcosa come git filter-branch --index-filter 'git rm --cached -rf subtree–folder1 subtree_folder2' HEAD.

Un altro modo, che probabilmente è eccessivo per ciò che si sta facendo, è la raccolta delle ciliegie. Il cherry-picking ti consente di riscrivere qualsiasi porzione della tua cronologia che ti piace con qualsiasi livello di dettaglio che ti piace: http://git-scm.com/docs/git-cherry-pick. Si vuole fare qualcosa di simile git reset --hard <HASH of commit that introduced the subtree>, seguita da una serie di

git cherry-pick -n <following commit hashes> 
git reset 
git add -p 
git commit 

per ogni successivo commit che aveva fatto.Ciò ti consentirà di rimuovere la sottostruttura da ogni commit effettuato in passato. È possibile fare riferimento a partly cherry-picking a commit with git per ulteriori informazioni sull'effettiva selezione delle ciliegie. Quando si è fatto con questa versione della cancellazione, si vuole rimuovere i vecchi commit che non fanno più parte della vostra filiale:

git reflog expire --expire-unreachable=now --all 
git gc --prune=now 

Altre domande a cui fa riferimento: How to move a branch backwards in git? Listing and deleting Git commits that are under no branch (dangling?)

Problemi correlati