2009-10-06 11 views
8

Mam popełnić w odległym + lokalny oddział i chcę rzucać, że zobowiązują się do historii i umieścić niektóre z nich na własnym oddziale.git: lepszy sposób na git powrócić bez dodatkowego powrócił popełnić

Zasadniczo, teraz mam:

  D---E---F---G master 

I chcę:

   E---G topic 
      /
      D master 

To powinno być zarówno w moim lokalnym oraz w (jest tylko jeden, zwany pochodzenie) zdalnego repozytorium .

Jaki jest najczystszy sposób na uzyskanie tego?

Ponadto, istnieją również inni ludzie, którzy sklonowane że repo i którzy wyrejestrowany oddział główny. Gdybym zrobił taką zmianę w zdalnym repo, czy "git pull" praca dla nich, aby dostać się do tego samego stanu?

Odpowiedz

7

Jeśli opublikowany następnie masz rację, że nie chcesz, aby ponownie napisać historię master. To, czego chcesz, to opublikowanie zatwierdzenia do opanowania, które przywraca stan, w którym było D przy zachowaniu jego bieżącej historii, aby inni użytkownicy mogli łatwo łączyć lub zmieniać swoją pracę.

Jeśli planujesz w pewnym momencie w przyszłości, aby scalić topic do master następnie co pewnie też chce zrobić, to zrobić nową wspólną podstawę między master i topic, tak, że kiedy nie później scalić topic, don” t stracić zatwierdzenia, które zostały cofnięte w master. Najłatwiej to zrobić, wykonując commit "ponownie" na samym końcu zatwierdzenia "cofnij", który resetuje master z powrotem do swojego pierwotnego stanu i opierając na nim nową gałąź topic.

# checkout master branch (currently at G) 
git checkout master 

# Reset the index to how we want master to look like 
git reset D 

# Move the branch pointer back to where it should be, leaving the index 
# looking like D 
git reset --soft [email protected]{1} 

# Make a commit (D') for the head of the master branch 
git commit -m "Temporarily revert E, F and G" 

# Create the new topic branch based on master. 
# We're going to make it on top of master and the 'undo' 
# commit to ensure that subsequent merges of master->topic 
# or topic->master don't merge in the undo. 
git checkout -b topic 

# Revert the undo commit, making a redo commit (G'). 
git revert HEAD 

Jako alternatywę można dokonały zobowiązuje E „F” i G „ponawianie każdą część osobno, ale jako E, F i G są już w swojej opublikowanej historii to chyba bardziej zrozumiałe, jeśli tylko odwoływać się do” cofnij 'commit i powiedz, że to zatwierdzenie jest cofane. Tak czy inaczej, robi to git revert.

Zasadniczo to, co wiesz, jest takie.

D -- E -- F -- G -- D'  <-- master 
        \ 
         \ 
         G' <-- topic 

najważniejszych rzeczy jest to, że nie został przepisany historii i temat jest oparty na pana tak scala nie przypadkowo stosować żadnych „Cofnij” zobowiązuje. Możesz teraz bezpiecznie przesyłać zarówno master i topic do zdalnego repozytorium.

+0

Dzięki, to jest dokładnie to, co zrobiłem teraz (także to, co zasugerowałem w niektórych komentarzach do Jefromi). Historia jest teraz nieco brzydka z powodu tego cofnięcia zatwierdzenia, ale nie mogę nic z tym zrobić. – Albert

+0

2 tygodnie git użytkownika tutaj. Czy nie byłoby łatwiej od pierwszego odgałęzienia G do G ', a następnie "git revert' G do D, w wyniku czego D'? W ten sposób nie musisz cofać/ponawiać niczego, co jest dla mnie o wiele bezpieczniejsze. (Mam już nieodwracalnie utracone zmiany z powodu zakłócenia 'git reset'.) – bart

+0

@bart, spójrz na' git reflog'. Rzeczy, które zostały wyłapane, a następnie spieprzone, powinny być zawsze możliwe do odzyskania przez reflog, przynajmniej przez kilka dni. Możesz jednak nieodwołalnie stracić zmiany, których nie udało Ci się kiedykolwiek zatwierdzić. – dubiousjim

4

Możesz przepisać swoją historię, jeśli chcesz, ale to zły pomysł, jeśli ktoś ma kopie historii. W takim przypadku prawdopodobnie użyjesz interaktywnego rebase: git rebase -i master topic. To da ci listę zatwierdzeń od mistrza do tematu, z podpowiedziami, jak się z nimi bawić. Po prostu musisz usunąć wiersz zawierający zatwierdzenie, które chcesz usunąć.

To powiedziawszy, muszę podkreślić, że jest to nieodpowiedzialne, aby to zrobić, jeśli ktoś ma taką historię. Musiałbyś wymusić przeniesienie go do centralnego repozytorium, a wszyscy inni musieliby naprawić swoje repozytorium, aby były zgodne, może być względnie proste lub złożone w zależności od okoliczności.

Istnieje fajna sekcja o nazwie "odzyskiwanie z bazy danych" w git-rebase man page omawiająca, jak sobie z tym poradzić, jeśli naprawdę się na to zdecydujesz.

Edit:

Dla prostej historii, wspólny scenariusz byłby po zmuszając push non-fastForward do centralnego repo (push -f), inni deweloperzy:

  • z powrotem ich starego mistrza: git branch -m master master_old
  • uzyskać aktualizacje i odtworzyć pana z pochodzenia: git remote update origin; git branch master origin/master
  • rebase wszystkie branże temat na nowy Master: git rebase --onto master master_old topic

Jeśli mają pracę w ich gałęzi, która nie jest jeszcze pochodzenia, będą musiały uzyskać bardziej wyszukane, przestawiając tę ​​pracę i wszystkie gałęzie tematyczne na nową pozycję mistrza ... to powinno dać ci pomysł, dlaczego tak przerażające jest przepisywanie historii, którą mają inni ludzie. Naprawdę, kiedy coś trafi do publicznego repozytorium, powinieneś traktować to jako ciężko i szybko zapisaną historię, a nie pracę w toku.

+0

OK, wielkie dzięki za te informacje. Więc to nie jest tak naprawdę rozwiązanie, ponieważ nie chcę robić takiego przymusu. Jakie byłoby najczystsze rozwiązanie, aby uzyskać podobny wynik? Jedną z nich, którą teraz myślę, jest odwrócenie E, F, G w master, a następnie stworzenie nowej gałęzi z tego stanu i cherry-pick E i G. Czy to jest coś, co można zrobić naturalnie? – Albert

+0

Nie ma * możliwości * usunięcia usunięcia z historii bez powodowania tego rodzaju problemów. Bez względu na to, co zrobisz, skierujesz swój master ref do zatwierdzenia, które nie ma poprzedniej pozycji mistrza w swojej historii. – Cascabel

+0

Jest to w dużej mierze adresowane w mojej odpowiedzi na twoją nową wersję tego pytania, ale aby odpowiedzieć na twoją uwagę: nie ma znaczenia, jak dostaniesz się do stanu, w którym przepisałeś historię mistrza. Nadal go przepisałeś. Jeśli wykonasz wszystkie te czynności * lokalnie *, wszystko jest w porządku. To się nazywa oczyszczanie. Jeśli robisz to do opublikowanej pracy, psujesz rzeczy, tworząc publiczne repozytywanie, któremu nikt nie może ufać, itp. – Cascabel

-3

znajdę git stash jest dość pomocny

Wystarczy schować go z dala i nie patrzeć na nią ponownie.

+2

Nie możesz przechować zmian, które już popełniłeś. –

+0

użyj 'git reset HEAD ^', aby wydać zatwierdzenie bez utraty zmian. – twig

Powiązane problemy