"Взаємодія з системою контролю версій. Інструкція для новачків".
Зображення взято десь з Хабру. Люблю цю картинку.
#git
Зображення взято десь з Хабру. Люблю цю картинку.
#git
Доречі, про системи контролю версій.
Вчора вперше за п'ять років знайомства з git мені згодився reflog. По роботі.
Картіна маслом.
Запушив коміт з двома новими файлами у свою feature-гілку. Дивлюся - а один з них мені і не потрібен. Видалив його, а потім, щоб не створювати нового коміту та не залишати непотрібний файл в історії, роблю
1.
Отож. Не той.
Маємо: В локальномі репозиторії файла нема (бо amend). У віддаленому - теж (бо force push). А у файлі був SQL строчок на п'ятнадцять, що шліфувався зо дві години.
Перша секунда після: йо...
Друга секунда: о, в мене ж є reflog, я про нього і на мітапі розповідав.
1.
3.
4. маю "втрачений" файл в локальному репозиторії
5. ???
6. профіт!
Мораль.
Git ніколи сам по собі не видаляє дані. І навіть після переписування історії можна знайти "втрачене" (але поки gc на репозиторії ніхто не запускав).
#git
Вчора вперше за п'ять років знайомства з git мені згодився reflog. По роботі.
Картіна маслом.
Запушив коміт з двома новими файлами у свою feature-гілку. Дивлюся - а один з них мені і не потрібен. Видалив його, а потім, щоб не створювати нового коміту та не залишати непотрібний файл в історії, роблю
1.
git commit --amend
2. git push --force origin my-feature
Здогадайтеся, чи той файл я видалив?..Отож. Не той.
Маємо: В локальномі репозиторії файла нема (бо amend). У віддаленому - теж (бо force push). А у файлі був SQL строчок на п'ятнадцять, що шліфувався зо дві години.
Перша секунда після: йо...
Друга секунда: о, в мене ж є reflog, я про нього і на мітапі розповідав.
1.
git reflog
2. знаходжу хеш того коміту, в якому був потрібний файл3.
git checkout хешКоміту -- шлях/до/файлу
(тільки не загубіть пробіли до і після двох дефісів)4. маю "втрачений" файл в локальному репозиторії
5. ???
6. профіт!
Мораль.
Git ніколи сам по собі не видаляє дані. І навіть після переписування історії можна знайти "втрачене" (але поки gc на репозиторії ніхто не запускав).
#git
Досить немала частина тих, хто працює з git, має хибне уявлення про термін "гілка" (branch).
Гілка (а точніше, ім'я гілки) - це динамічний вказівник на коміт. Все.
Чому динамічний? Коли на гілці з'являється новий коміт, вказівник автоматично переміщується на нього. Зазвичай гілка не вказує на один і той самий коміт впродовж усього свого існування (так, таке може бути, але лише в окремих випадках).
На малюнку "
Більшість команд, що мають на увазі коміт, з задоволенням приймуть ім'я гілки: наприклад,
Але навпаки - не завжди: наприклад,
А ось якщо ми бажаємо зробити постійний вказівник на коміт, але звичайний хеш нас чомусь не задовольняє, то ми можемо використати тег. Та це вже зовсім інша історія...
#git
Гілка (а точніше, ім'я гілки) - це динамічний вказівник на коміт. Все.
Чому динамічний? Коли на гілці з'являється новий коміт, вказівник автоматично переміщується на нього. Зазвичай гілка не вказує на один і той самий коміт впродовж усього свого існування (так, таке може бути, але лише в окремих випадках).
На малюнку "
master" - це вказівник на коміт a11 (коміти позначені умовно - для спрощення), "feature-1" - вказівник на c4, а "feature-2" - вказівник на b5.Більшість команд, що мають на увазі коміт, з задоволенням приймуть ім'я гілки: наприклад,
git diff.Але навпаки - не завжди: наприклад,
git checkout. Checkout на коміт спрацює, та зробить він трохи не те, що вам хотілося.А ось якщо ми бажаємо зробити постійний вказівник на коміт, але звичайний хеш нас чомусь не задовольняє, то ми можемо використати тег. Та це вже зовсім інша історія...
#git
або
Як вилучити з репозиторію зайві файли, що були додані декілька комітів тому
Минулого тижня товариш з сусідньої команди звернувся з запитанням.
Дано
1. Коміт, до якого помилково потрапив зайвий файл. Також в ньому наявні інші (потрібні) зміни.
2. Після нього зроблено ще декілька корисних комітів.
Треба
Вилучити зайвий файл з історії.
Що нам НЕ підійде
1. Просто видалити файл та зробити коміт.
2. Revert:
git revert хешКоміту.3. Amend:
git commit --amend.4. Hard reset:
git reset --hard хешКоміту.#git
...Чому не підійде?
1. При "просто видаленні" файл зникне з файлової системи, але залишиться в історії.
2. Revert, як і в п. 1, не прибере зайвий файл з історії, а ще ми втратимо ті потрібні зміни, що були закомічені разом з нашим зайвим файлом. Так, ці зміни можна буде отримати досить законними шляхами, але нашо ті танці? Все одно історія не буде змінена, що унеможливлює використання цього способу.
3. Amend виправляє лише останній коміт. У нас проблема не в останньому коміті, а глибше.
4. Після хард резету ми втратимо усі корисні коміти, що зроблені після проблемного, а також ті потрібні зміни, що знаходяться у проблемному.
Що ми будемо робити?
Ми будемо робити інтерактивний рібейз.
Інтерактивний рібейз - це один зі способів переписування історії. Він дозволяє редагувати коміти, переміщувати, зливати їх і т.ін. При цьому гілку ми будемо перебазовувати саму на себе.
Як ми будемо це робити?
Спочатку вилучимо зайвий файл та створимо з цього коміт. Потім запустимо інтерактивний рібейз на коміт, що передує проблемному коміту. Перемістимо коміт-рятівник так, щоб він знаходився одразу після проблемного, та вкажемо опцію "squash", тобто зіллємо з попереднім, проблемним. В результаті цього злиття в один і той самий коміт потраплять обидва діффа - той, де зайвий файл створюється, та той, де він видаляється. Повна анігіляція файлу. Як матерія та антиматерія.
#git
1. При "просто видаленні" файл зникне з файлової системи, але залишиться в історії.
2. Revert, як і в п. 1, не прибере зайвий файл з історії, а ще ми втратимо ті потрібні зміни, що були закомічені разом з нашим зайвим файлом. Так, ці зміни можна буде отримати досить законними шляхами, але нашо ті танці? Все одно історія не буде змінена, що унеможливлює використання цього способу.
3. Amend виправляє лише останній коміт. У нас проблема не в останньому коміті, а глибше.
4. Після хард резету ми втратимо усі корисні коміти, що зроблені після проблемного, а також ті потрібні зміни, що знаходяться у проблемному.
Що ми будемо робити?
Ми будемо робити інтерактивний рібейз.
Інтерактивний рібейз - це один зі способів переписування історії. Він дозволяє редагувати коміти, переміщувати, зливати їх і т.ін. При цьому гілку ми будемо перебазовувати саму на себе.
Як ми будемо це робити?
Спочатку вилучимо зайвий файл та створимо з цього коміт. Потім запустимо інтерактивний рібейз на коміт, що передує проблемному коміту. Перемістимо коміт-рятівник так, щоб він знаходився одразу після проблемного, та вкажемо опцію "squash", тобто зіллємо з попереднім, проблемним. В результаті цього злиття в один і той самий коміт потраплять обидва діффа - той, де зайвий файл створюється, та той, де він видаляється. Повна анігіляція файлу. Як матерія та антиматерія.
#git
Минулого тижня.
Той самий момент, коли на робочому ПК закомітив жменю правок, вдома раптом закортіло трохи доробити (чи то Роботун напав, чи щось таке)... але "
Не виконав у повному обсязі золоте правило
"
#git
Той самий момент, коли на робочому ПК закомітив жменю правок, вдома раптом закортіло трохи доробити (чи то Роботун напав, чи щось таке)... але "
git pull origin" каже, що все актуальне. Бо не запушив.Не виконав у повному обсязі золоте правило
"
git commit, git push, get out" 😔#git
Git та мертва гілка
А чи доводилося вам стикатися з ситуацією, коли в локальному репозиторії залишилося посилання на віддалену гілку, що вже була видалена у віддаленому репозиторії?
Спроба видалити через
"
призводить до помилки - бо гілки ж там вже немає.
Щоб усе це прибрати, використовуюється команда
"
Якщо тре лише подивитися, що саме буде видалено, та не видаляти, додатково використовується ключ
#git
А чи доводилося вам стикатися з ситуацією, коли в локальному репозиторії залишилося посилання на віддалену гілку, що вже була видалена у віддаленому репозиторії?
Спроба видалити через
"
git push віддаленийРепозиторій :віддаленаГілка"призводить до помилки - бо гілки ж там вже немає.
Щоб усе це прибрати, використовуюється команда
"
git remote prune віддаленийРепозиторій".Якщо тре лише подивитися, що саме буде видалено, та не видаляти, додатково використовується ключ
--dry-run.#git
Інколи при роботі з системами контролю версій є потреба повернути один файл у той стан, в якому він був колись. Наприклад, у конкретному коміті.
Щодо гілки, формулювання "стан файлу, в якому він був колись" тут буде не зовсім точним, краще сказати "стан файлу з альтернативної реальності" 😏
P.S.: так-так,
#git
git checkout коміт файлЗамість коміту ми можемо вказати тег або ім'я гілки.
Щодо гілки, формулювання "стан файлу, в якому він був колись" тут буде не зовсім точним, краще сказати "стан файлу з альтернативної реальності" 😏
P.S.: так-так,
checkout вміє не лише перемикати гілкИ.#git