Git: Як переходити між коммітами вперед і назад


76

У мене є новачкове запитання про Git:

Мені потрібно рухатись вперед-назад в історії філії. Це означає, що мені потрібно повернути всі файли до стану, в якому вони перебували в якійсь старій редакції, а потім мені потрібно повернутися до останнього стану у сховищі. Мені не потрібно робити зобов’язання.

З SVN це було б

svn up -r800

дістатися до версії 800 та

svn up

для синхронізації зі сховищем.

Я знаю хеш коміту, до якого хочу повернутися, тому спробував

git reset <hash>

що, здається, привело мене туди. Але потім я спробував

git pull

але це скаржиться на конфлікти.

Тож як правильно рухатись по історії філії?

Я думаю з точки зору SVN, тож не соромтеся вказати мені якийсь гарний підручник. Зауважте, що я вже перевірив http://git.or.cz/course/svn.html та http://www.youtube.com/watch?v=8dhZ9BXQgc4 .

Дякую, Ондра.


1
Примітка: Я звик уникати git pullвзагалі. Натомість я використовую git fetch --allпсевдонім до gubash і постійно gitkвідкриваю, переглядаючи всі гілки - див. Перегляд -> редагувати -> встановіть усі 4 прапорці. Потім я рухаюся, використовуючи git resetабо gist stash+ git co, залежно від того, що мені потрібно.
Ondra Žižka

Відповіді:


71

Ну, я теж колишній користувач svn, і тепер використовую git для всіх своїх проектів.

Використовуючи git, вам слід змінити спосіб мислення з архітектури клієнт-сервер, яка використовується в svn. У svn кожна зміна потребує з'єднання з сервером. Використовуючи git, ваше репозиторій знаходиться в робочому каталозі. Вам не потрібне з'єднання для кожної дії репо.

Використовуйте git pushта git pullсинхронізуйте лише з репо. Подумайте про це як про використання rsync або будь-яке рішення для резервного копіювання, щоб зробити два місця абсолютно однаковими. Так само, як ви підключаєте зовнішній жорсткий диск для резервного копіювання, тоді вміст у ньому збігається із вмістом у вашому основному. Це використання git pullі git push.

Якщо ви просто хочете переглядати історію вперед і назад, робіть це, використовуючи git checkout. Перегляньте ідентифікатор редакції за допомогою git history. Якщо ви використовуєте Linux, використовуйте, gitkщоб побачити дерево версій. У Windows, черепаха git може відображати його, використовуючи графік версій.

Щоб повернутися до останньої версії, використовуйте git checkout master. Перш ніж виконувати будь-яку команду, завжди змушуйте себе це робити git status. Ця команда відображатиме все, що вам потрібно знати про поточний стан репо та про те, які дії потрібно зробити, щоб виправити ситуацію. Перш ніж робити git pullі git push, краще переконатися, що git statusрезультат містить текст working directory clean.

Якщо вам потрібно повернути файл до попередньої версії, ви можете зробити це за допомогою git merge. Перш ніж робити це у файлі, спершу протестуйте його за допомогою git diff. Приклад: git diff rev1:rev2 filename. Він буде роздруковувати будь-яке інше між двома версіями. Зміни у версії 1 буде замінено змінами у версії 2. Отже, щоб повернути, rev2 буде старшим, ніж rev1. Після того, як ви задовольнили результатом різниці, зробіть це за допомогою git merge, просто замініть diffна merge, всі інші параметри залишаються незмінними.

Сподіваюся, це вам допоможе. Головне - побачити, що ваш робочий каталог - це ваше репо. Розуміння цього допоможе вам використовувати git до повної можливості. Удачі.


39

Ви можете використовувати git checkoutдля оформлення будь-якого коміту, а потім використовувати його з назвою гілки, щоб повернутися до іменованої гілки.

git checkoutза допомогою ідентифікатора коміту, а не імені гілки, ви переміщуєтеся з будь-якої іменованої гілки і переходить до того, що називається відокремленою головою .

Якщо ви використовуєте, git resetтоді ваша філія повернеться до старого стану, залишивши без уваги останні комміти, які, ймовірно, не є тим, що ви хочете.


Що checkoutнасправді робить? Чи змінює це файли на стан даного коміту, шляхом зворотного застосування патчів комітів між поточним станом і станом даного коміту?
Ondra Žižka

Я знайшов git resetі git reset origin. Я не буду робити жодних комітів, тому не має значення, чи втрачаю я останні коміти, наскільки це легко відновити (що означає, однією командою).
Ondra Žižka

1
git checkout не робить зміни постійними. Для цього використовуйте git merge. Дивіться мої відповіді.
Донні Курня

1
checkout reset індексує / кеш / проміжну область до дерева, призначеного даним комітом, а потім оновлює робоче дерево відповідно кешу. Не потрібно повторно застосовувати патч; він просто використовує дерево, як на даному коміті. (Він також перевіряє помилки та оновлює зареєстровану гілку, якщо ви передаєте їй назву філії.)
CB Bailey

30

Інші відповіді є інформативними, але я вважаю, що це найближче до того, що хоче ОП:

Додайте ці дві функції до вашого ~ / .bashrc:

# checkout prev (older) revision
git_prev() {
    git checkout HEAD~
}

# checkout next (newer) commit
git_next() {
    BRANCH=`git show-ref | grep $(git show-ref -s -- HEAD) | sed 's|.*/\(.*\)|\1|' | grep -v HEAD | sort | uniq`
    HASH=`git rev-parse $BRANCH`
    PREV=`git rev-list --topo-order HEAD..$HASH | tail -1`
    git checkout $PREV
}

Використання:

$ git_prev
Previous HEAD position was 7042c8a... Commit message2
HEAD is now at d753ecc... Commit message1

$ git_next
Previous HEAD position was d753ecc... Commit message1
HEAD is now at 7042c8a... Commit message2

Примітка : Ці команди завжди входять у від'єднаний стан HEAD . Якщо ви git_prevперейшли git_nextз перевіреної на даний момент гілки, ви повернетесь до останньої версії, але ви будете у від'єднаному стані HEAD. Зробити, git checkout BRANCH_NAMEщоб повернутися до нормального стану.


Після того, як ви робите подібні речі, погляньте на псевдоніми git, можливо, вартий уваги.
реабілітація

Мені подобається ця відповідь, і вона працювала хвилину, але тепер, коли я запускаю git_next, я отримую цеusage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num] [-B num] [-C[num]] [-e pattern] [-f file] [--binary-files=value] [--color=when] [--context[=num]] [--directories=action] [--label] [--line-buffered] [--null] [pattern] [file ...]
Squirrl

11

Спробуйте git reflog, це перелічує коміти та перевірки, які ви зробили для перемикання між комітами, навіть коміти, які ви втратили під час оформлення замовлення, до попереднього коміту.

Тоді ви можете спробувати git checkout <hash of a commit>перейти до цього коміту.

Сподіваюся, це допомагає!


7

Щоб перевірити іншу версію файлу, використовуйте

git checkout rev -- filename

Де rev може бути ідентифікатором коміту, назвою гілки, назвою тегу або відносною версією.

Використовуйте git log, gitkщоб переглянути версії файлу, щоб побачити, яку версію файлу ви хочете.

Щоб зробити цю версію файлу постійною, вам потрібно зафіксувати файл: git add filename; git commit filename

Я не рекомендував git pullби перевіряти версії, оскільки це об’єднує - потенційно змінюючи ваш поточний стан.

Вам не потрібно користуватися git resetв цьому випадку, якщо ви git addне вирішите не створювати файл.


солодкий джибус будь обережним, роблячи це. Мій колега зробив цю команду, щоб спробувати зміни в моїй гілці, знищив мою роботу приблизно на тиждень і виштовхнув її до репо, виконавши це ...
Карина

До тих пір, поки ваш колега не зробить push -f, ви завжди можете повернути його коміт і відновити відсутні роботи. Якщо у вас є доступ до репо, до якого він натискав, навіть силове натискання можна відновити за допомогою git reflog. Крім того, якщо у вас все ще є ваша філія, її можна відновити. Але так, треба бути обережним.
Jamey Hicks
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.