Расширенное руководство по Git: Git Stash, сброс, перебазирование и многое другое

Опубликовано: 2022-03-11

Каждый разработчик должен хорошо разбираться в управлении версиями, а Git стал стандартом де-факто для контроля версий в разработке программного обеспечения.

Однако часто разработчики изучают только несколько простых команд и упускают из виду всю мощь истории Git и других вещей, которые Git может сделать для повышения вашей эффективности. Например, в Git очень легко управлять выпусками с помощью git tag .

Я прошел продвинутый онлайн-курс по Git (с Github) и продолжил преподавать класс Git для начинающих совместно с Github. Когда я заметил, что технических статей о моих любимых функциях Git не так много, я ухватился за возможность поделиться ими с моими коллегами-разработчиками. В этом посте вы узнаете, как использовать следующие расширенные функции Git:

  • git stash , который делает временное локальное сохранение вашего кода
  • git reset , который позволяет привести код в порядок перед выполнением коммита.
  • git bisect — функция, позволяющая выявлять плохие коммиты.
  • git squash , который позволяет комбинировать ваши коммиты
  • git rebase , который позволяет применять изменения из одной ветки в другую

Git Тайник

Git stash позволяет сохранить код без фиксации. Чем это полезно? Представьте себе следующий сценарий:

Вы уже сделали три чистых и аккуратных коммита, но у вас также есть незафиксированный код, который довольно беспорядочный; вы не захотите фиксировать его, не удалив сначала код отладки. Затем по какой-то причине вам вдруг нужно заняться другой задачей и переключиться на другую ветку. Это часто может произойти, если вы находитесь в своей main ветке и забыли создать новую ветку для своей функции. Прямо сейчас ваш код выглядит так:

 $ git status On branch my-feature Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: css/common.scss no changes added to commit (use "git add" and/or "git commit -a")
 $ git diff diff --git a/css/common.scss b/css/common.scss index 2090cc4..90fd457 100644 --- a/css/common.scss +++ b/css/common.scss @@ -13,6 +13,6 @@ body { font-family: "Proxima Nova", Arial, sans-serif; font-size: 13px; - color: #333; + color: red; background-color: #f00; }

Когда вы запускаете git stash , незафиксированный код исчезает без фиксации. Сохранение похоже на сохранение временной локальной фиксации в вашей ветке. Невозможно отправить тайник в удаленный репозиторий, поэтому тайник предназначен только для вашего личного использования.

 $ git stash Saved working directory and index state WIP on my-feature: 49ee696 Change text color

Теперь ваша ветка выглядит так, как будто вы сделали последний коммит. Теперь вы можете безопасно менять ветки, не теряя код и не запутываясь в коммите. Когда вы вернетесь в свою ветку и запустите git stash list , вы увидите список тайников, который выглядит примерно так:

 $ git stash list stash@{0}: WIP on my-feature: 49ee696 Change text color

Вы можете легко повторно применить спрятанный контент, запустив git stash apply . Вы также можете применить определенный тайник (если вы спрятали его более одного раза), запустив git stash apply stash@{1} («1» обозначает предпоследний тайник). Вот пример хранения более одного коммита и применения другого тайника:

 $ git diff diff --git a/css/common.scss b/css/common.scss index 2090cc4..90fd457 100644 --- a/css/common.scss +++ b/css/common.scss @@ -13,6 +13,6 @@ body { font-family: "Proxima Nova", Arial, sans-serif; font-size: 13px; - color: #333; + color: red; background-color: #f00; } $ git stash Saved working directory and index state WIP on my-feature: 49ee696 Change text color $ git diff diff --git a/css/common.scss b/css/common.scss index 2090cc4..b63c664 100644 --- a/css/common.scss +++ b/css/common.scss @@ -13,6 +13,6 @@ body { font-family: "Proxima Nova", Arial, sans-serif; font-size: 13px; - color: #333; + color: red; background-color: #f00; } $ git stash Saved working directory and index state WIP on my-feature: 49ee696 Change text color
 $ git stash list stash@{0}: WIP on my-feature: 49ee696 Change text color stash@{1}: WIP on my-feature: 49ee696 Change text color stash@{2}: WIP on my-feature: 49ee696 Change text color $ git stash apply stash@{2} On branch my-feature Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: css/common.scss no changes added to commit (use "git add" and/or "git commit -a")

git stash apply stash@{2} применил самый старый спрятанный код, когда мы изменили цвет текста на красный.

 $ git diff diff --git a/css/common.scss b/css/common.scss index 2090cc4..90fd457 100644 --- a/css/common.scss +++ b/css/common.scss @@ -13,6 +13,6 @@ body { font-family: "Proxima Nova", Arial, sans-serif; font-size: 13px; - color: #333; + color: red; background-color: #f00; }

Если вы решите не коммитить свою работу после восстановления тайника, вы можете запустить git checkout . , который сбрасывает весь незафиксированный код.

Еще один пример того, как использовать Git stash: скажем, у вас есть несколько новых файлов, в одном из которых есть ошибка. Оставьте все, кроме предполагаемого файла ошибки, неустановленными (код должен быть подготовлен, чтобы его можно было спрятать), затем вы можете спрятать этот файл и устранить проблему. Если спрятанный файл не был проблемой, вы можете восстановить тайник.

 $ git status On branch my-feature Untracked files: (use "git add <file>..." to include in what will be committed) css/colors.scss nothing added to commit but untracked files present (use "git add" to track)
 $ git add css/colors.scss $ git stash Saved working directory and index state WIP on my-feature: 0d8deef delete colors $ git status On branch my-feature nothing to commit, working tree clean $ git stash apply stash@{0} On branch my-feature Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: css/colors.scss

Вы также можете перенести свои спрятанные коммиты в новую ветку функций или ветку отладки, используя ветку git stash branch :

 $ git status On branch my-feature Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: css/common.scss no changes added to commit (use "git add" and/or "git commit -a") $ git stash Saved working directory and index state WIP on my-feature: 66f3f3b Add colors file $ git stash branch debugging-branch M css/common.scss Switched to a new branch 'debugging-branch' Unstaged changes after reset: M css/common.scss On branch debugging-branch Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: css/common.scss Dropped refs/stash@{0} (d140624f60d8deef7bceb0d11fc80ed4fd47e0a1)

Обратите внимание, что когда вы применяете тайник, тайник не удаляется. Вы можете удалить тайники по отдельности с помощью git drop или удалить все тайники с помощью git stash clear :

 $ git stash list stash@{0}: WIP on my-feature: 66f3f3b Add colors file stash@{1}: WIP on my-feature: 0d8deef delete colors stash@{2}: WIP on my-feature: 49ee696 Change text color $ git stash drop stash@{2} Dropped stash@{2} (8ed6d2ce101aa2e28c8ccdc94cb12df8e5c468d6) $ git stash list stash@{0}: WIP on my-feature: 66f3f3b Add colors file stash@{1}: WIP on my-feature: 0d8deef delete colors $ git stash clear $ git stash list $

Git сброс

Если вы окажетесь в ситуации, когда вы случайно зафиксировали какой-то беспорядочный код, вы можете сделать «мягкий» сброс. Это означает, что код выглядит так, как будто он еще не был зафиксирован. Затем вы можете привести свой код в порядок в своей среде IDE, прежде чем сделать более чистую фиксацию. Для этого вы можете запустить git reset --soft HEAD~1 . Это сбросит самый последний коммит. Вы можете сбросить несколько коммитов, изменив номер после ~ например git reset --soft HEAD~2 .

 $ git reset --soft HEAD~1 $ git status On branch debugging-branch Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: css/common.scss Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: css/common.scss
 $ git diff diff --git a/css/common.scss b/css/common.scss index 2090cc4..90fd457 100644 --- a/css/common.scss +++ b/css/common.scss @@ -13,6 +13,6 @@ body { font-family: "Proxima Nova", Arial, sans-serif; font-size: 13px; - color: $grey; + color: red; background-color: #f00; }

Сброс Git немного сбивает с толку, особенно при обучении новых пользователей Git. Мягкий сброс должен быть зарезервирован для настоящей ошибки, тогда как тайник можно использовать для замены кода.

Вы также можете выполнить полный сброс ( git reset --hard HEAD~1 ). Этот тип сброса по существу стирает ваш последний коммит. Вы должны быть очень осторожны при выполнении аппаратных сбросов, особенно если вы нажимаете свою ветку, так как нет возможности восстановить вашу фиксацию.

Git пополам

Мой любимый инструмент Git — git bisect . Мне это нужно было всего несколько раз, но когда я это сделал, это было бесценно! В основном я использовал его для больших кодовых баз, где была проблема, для которой никто не нашел основную причину, даже после энергичной отладки.

git bisect , по сути, выполняет бинарный поиск между двумя заданными коммитами, а затем предоставляет вам детали конкретного коммита. Сначала вам нужно дать Git хороший коммит, когда вы знаете, что ваша функциональность работает, и плохой коммит. Обратите внимание, что пока у вас есть один хороший коммит и один плохой, между коммитами могут быть годы (хотя чем дальше во времени вы уходите, тем сложнее это становится!).

Самое забавное в git bisect то, что вы обычно не знаете, кто написал ошибочный коммит, когда начинаете. Радость узнать, где была обнаружена ошибка, не раз заставляла нескольких коллег толпиться вокруг моего компьютера!

Для начала просмотрите ветку с ошибками и найдите хорошие коммиты. Вам нужно просмотреть историю коммитов и найти хэш коммита, а затем проверить этот конкретный коммит и протестировать свою ветку. Как только вы найдете хорошее и плохое место для работы, вы можете запустить git bisect .

В этом сценарии текст на этом веб-сайте, который мы создали, красный (хотя для этого мог бы понадобиться дизайнер пользовательского интерфейса), но мы не знаем, как и когда он стал красным. Это очень простой пример, в реальном сценарии у вас, вероятно, была бы гораздо менее очевидная проблема, например, форма не отправлялась/не функционировала.

Когда мы запускаем git log , мы видим список коммитов на выбор.

 $ git log commit a3cfe7f935c8ad2a2c371147b4e6dcd1a3479a22 (HEAD -> main) Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:52:57 2021 +0100 Update .gitignore file for .DS_Store commit 246e90977790967f54e878a8553332f48fae6edc Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:51:23 2021 +0100 Change styling of page commit d647ac489ad43b3c6eaea5aceb02b0a7d7e5cf8e Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:50:48 2021 +0100 Change text color commit 032a41136b6653fb9f7d81aef573aed0dac3dfe9 Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:42:57 2021 +0100 Change text color commit 246e90977790967f54e878a8553332f48fae6edc Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:41:23 2021 +0100 delete colors commit d647ac489ad43b3c6eaea5aceb02b0a7d7e5cf8e Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:50:48 2021 +0100 Change text color commit ce861e4c6989a118aade031020fd936bd28d535b Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:07:36 2021 +0100 ...

Если я открою свою веб-страницу с самым последним хэшем коммита, текст станет красным, поэтому я знаю, что у меня проблема.

Git bisect, шаг 1: веб-страница с красным текстом.

Теперь мы запускаем bisect и сообщаем Git, что у нас плохой коммит.

 $ git bisect start $ git bisect bad 8d4615b9a963ef235c2a7eef9103d3b3544f4ee1

Теперь вернемся в прошлое, чтобы попытаться найти коммит, где текст не был красным. Здесь я пытаюсь проверить свой первый коммит…

 $ git checkout ce861e4c6989a118aade031020fd936bd28d535b Note: checking out 'ce861e4c6989a118aade031020fd936bd28d535b'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new-branch-name> HEAD is now at ce861e4 Add CSS styles

…и обновление веб-страницы…

Git bisect, шаг 2: веб-страница с черным текстом.

Текст больше не красный, так что это хороший коммит! Чем новее коммит, то есть чем ближе к плохому коммиту, тем лучше:

 $ git checkout d647ac489ad43b3c6eaea5aceb02b0a7d7e5cf8e Previous HEAD position was ce861e4c6989a118aade031020fd936bd28d535b Add CSS styles HEAD is now at d647ac4 Change text color

Теперь Git сообщит вам, сколько коммитов он должен найти, прежде чем найдет правильный. Количество коммитов, которые будет проходить Git, зависит от того, сколько коммитов находится между хорошим и плохим коммитом (чем дольше отрезок времени, тем больше раз Git нужно выполнить итерацию).

Теперь вам нужно снова протестировать свою ветку и посмотреть, исчезла ли ваша проблема. Иногда это может быть немного обременительно, если вы регулярно обновляете модули, поскольку вам может потребоваться переустановить модули узлов в репозитории внешнего интерфейса. Если были обновления базы данных, вам также может потребоваться обновить их.

git bisect автоматически проверяет коммит между вашими хорошими и плохими коммитами. Здесь он оценивает один шаг, чтобы найти плохой коммит.

 $ git bisect good 1cdbd113cad2f452290731e202d6a22a175af7f5 Bisecting: 1 revision left to test after this (roughly 1 step) [ce861e4c6989a118aade031020fd936bd28d535b] Add CSS styles $ git status HEAD detached at ce861e4 You are currently bisecting, started from branch '8d4615b'. (use "git bisect reset" to get back to the original branch)

Обновите страницу и посмотрите, исчезла ли ваша проблема. Проблема все еще существует, поэтому мы сообщаем Git, что это все еще плохой коммит. На этот раз не нужно ссылаться на хэш фиксации, так как Git будет использовать фиксацию, которую вы проверили. Нам нужно будет повторять этот процесс, пока Git не пройдет все возможные шаги.

 $ git bisect bad Bisecting: 0 revisions left to test after this (roughly 0 steps) [cbf1b9a1be984a9f61b79ae5f23b19f66d533537] Add second paragraph to page

Обновите страницу, и наша проблема снова исчезнет, ​​так что это хороший коммит:

Git bisect, шаг 3: та же веб-страница с дополнительным черным текстом.

На этом этапе Git обнаружил первый плохой коммит:

 $ git bisect good ce861e4c6989a118aade031020fd936bd28d535b is the first bad commit commit ce861e4c6989a118aade031020fd936bd28d535b Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:52:57 2021 +0100 Add CSS styles :000000 100644 0000000000000000000000000000000000000000 092bfb9bdf74dd8cfd22e812151281ee9aa6f01a M css

Теперь мы можем использовать git show , чтобы показать сам коммит и определить проблему:

 $ git show ce861e4c6989a118aade031020fd936bd28d535b commit ce861e4c6989a118aade031020fd936bd28d535b Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:52:57 2021 +0100 Add CSS styles diff --git a/css/base.scss b/css/base.scss index e69de29..26abf0f 100644 --- a/css/base.scss +++ b/css/base.scss @@ -1,7 +1,7 @@ body { background-color: $white; margin: 0px; line-height: 20px; - color: $grey; + color: red; }

Когда вы закончите, вы можете запустить git bisect reset , чтобы вернуть вашу ветку в нормальное рабочее состояние.

Чем ближе коммиты друг к другу, тем легче Git сможет найти проблему, но я уже делал 10 шагов раньше и по-прежнему легко находил плохой коммит. Не гарантируется, что он сработает, но большую часть времени он находил проблему для меня. Поздравляем, теперь вы археолог кода!

Сокращение ваших коммитов

Раньше я работал полный рабочий день над проектом с открытым исходным кодом для глобальной организации и быстро понял, насколько важно сжимать или комбинировать ваши коммиты. Я думаю, что это отличная привычка, даже если ваш работодатель этого не требует. Это особенно важно для других разработчиков, которым потребуется просмотреть и отредактировать созданные вами функции позже.

Зачем раздавливать ваши коммиты?

  • Участникам вашего репозитория легче читать. Представьте, что у вас есть такой список коммитов:
    • Реализовать карусельный слайдер
    • Добавьте стиль в карусель
    • Добавьте кнопки в карусель
    • Исправить странную проблему в IE с каруселью
    • Отрегулируйте поля в карусели

    Гораздо проще объединить их в один коммит с надписью «Добавить карусель на домашнюю страницу».

  • Это побуждает вас делать сообщения о коммитах понятными и актуальными, если каждый раз, когда вы делаете запрос на включение, вам приходится сжимать свои коммиты в один. Сколько раз вы видели коммит под названием «WIP», «исправление для страницы входа» или «исправить опечатку»? Важно иметь соответствующие названия коммитов, например, «Исправление ошибки для страницы входа № 444 — исправить мерцание из-за отсутствия функции $scope».

Причина, по которой вы не хотите удалять свои коммиты, может заключаться в том, что вы работаете над очень подробной и длинной функцией и хотите вести ежедневную историю для себя на случай, если позже вы столкнетесь с ошибками. Тогда вашу функцию будет легче отлаживать. Тем не менее, когда вы проверяете свою функцию в своей основной ветке и уверены, что она не содержит ошибок, все же имеет смысл удалить ее.

В этом сценарии я сделал пять коммитов, но все они связаны с одной фичей. Мои сообщения коммитов также слишком тесно связаны между собой, чтобы их можно было выделить отдельно — все мои коммиты посвящены стилю страницы для этой новой функции:

 $ git log commit a8fbb81d984a11adc3f72ce27dd0c39ad24403b7 (HEAD -> main) Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 11:16:10 2021 +0100 Import colors commit e2b3ddd5e8b2cb1e61f88350d8571df51d43bee6 Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 11:15:32 2021 +0100 Add new color commit d647ac489ad43b3c6eaea5aceb02b0a7d7e5cf8e Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:50:48 2021 +0100 Change text color commit c005d9ceeefd4a8d4e553e825fa40aaafdac446e Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 09:59:57 2021 +0100 Add CSS styles commit 9e046b7df59cef07820cc90f694fabc666731bd2 Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 09:56:28 2021 +0100 Add second paragraph to page commit 5aff973577d67393d914834e8af4c5d07248d628 Author: Ursula Clarke <[email protected]> Date: Mon Jan 10 16:04:22 2021 +0100 Add colors CSS file and edit background color

Вы также можете использовать git merge --squash , но я думаю, что понятнее использовать rebase , потому что, когда вы выбираете свои коммиты, легче увидеть описание коммита. Если вы запускаете git merge --squash , вам сначала нужно выполнить полный сброс ваших коммитов ( git reset --hard HEAD~1 ), и легко запутаться, сколько именно коммитов вам нужно сделать. Я считаю, что git rebase более нагляден.

Начните с запуска git rebase -i --root и ваш текстовый редактор по умолчанию в командной строке откроется со списком ваших коммитов:

 pick eb1eb3c Update homepage pick 5aff973 Add colors CSS file and edit background color pick 9e046b7 Add second paragraph to page pick c005d9c Add CSS styles pick d647ac4 Change text color pick e2b3ddd Add new color pick a8fbb81 Import colors # Rebase a8fbb81 onto b862ff2 (7 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out

Вы можете просто захотеть удалить последние несколько коммитов, и в этом случае вы можете запустить git rebase -i HEAD~3 и получить три последних коммита:

 pick eb1eb3c Update homepage pick 5aff973 Add colors CSS file and edit background color pick 9e046b7 Add second paragraph to page # Rebase b862ff2..9e046b7 onto b862ff2 (3 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out

Теперь мы можем объединить все коммиты в первый коммит, как показано ниже.

 pick eb1eb3c Update homepage squash 5aff973 Add colors CSS file and edit background color squash 9e046b7 Add second paragraph to page # Rebase b862ff2..9e046b7 onto b862ff2 (3 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out

Когда вы сохраните файл, Git откроет ваше сообщение фиксации для редактирования.

 # This is a combination of 3 commits. # This is the 1st commit message: Update homepage # This is the commit message #2: Add colors CSS file and edit background color # This is the commit message #3: Add second paragraph to page # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Wed Jan 13 18:31:28 2021 +0100 # # interactive rebase in progress; onto b862ff2 # Last commands done (3 commands done): # squash 5aff973 Add colors CSS file and edit background color # squash 9e046b7 Add second paragraph to page # No commands remaining. # You are currently rebasing branch 'main' on 'b862ff2'. # # Changes to be committed: # new file: .gitignore # new file: css/base.css # new file: css/base.scss # new file: css/colors.css # new file: css/colors.css.map # new file: css/colors.scss # new file: css/common.css # new file: css/common.scss # new file: index.html #

Пока мы делаем rebase, мы также можем отредактировать описание коммита, чтобы его было легче читать.

 Implement new design for homepage. Add .gitignore file for Sass folder. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. #

Сохраните этот файл еще раз, и все готово! Когда мы еще раз взглянем на журнал Git, мы увидим, что есть только один чистый коммит.

 [detached HEAD 574ec7e] Implement new design for homepage. Add .gitignore file for Sass folder. Date: Wed Jan 13 18:31:28 2021 +0100 10 files changed, 215 insertions(+) create mode 100644 .gitignore create mode 100644 css/base.css create mode 100644 css/base.scss create mode 100644 css/colors.css create mode 100644 css/colors.css.map create mode 100644 css/colors.scss create mode 100644 css/common.css create mode 100644 css/common.scss create mode 100644 index.html create mode 100644 verylargefile.txt Successfully rebased and updated refs/heads/main. $ git log commit 574ec7e5d7d7a96427e049cad9806cdef724aedd (HEAD -> main) Author: Ursula Clarke <[email protected]> Date: Wed Jan 13 18:31:28 2021 +0100 Implement new design for homepage. Add .gitignore file for Sass folder.

Git перебазировать

Разработчики обычно не решаются использовать git rebase , потому что знают, что rebase можно использовать для безвозвратного удаления файлов из вашей кодовой базы.

Как мы видели выше, git rebase можно использовать для сохранения вашего кода и его очистки, а также для удаления — но что, если вы действительно хотите навсегда удалить файл из истории?

Однажды я был свидетелем сценария, когда член нашей команды разработчиков случайно зафиксировал очень большой файл в кодовой базе. Это была часть гораздо большей ветки, поэтому большой файл остался незамеченным при проверке кода и был ошибочно добавлен в основную ветку. Это становилось проблемой всякий раз, когда кто-то хотел повторно клонировать репозиторий - загрузка занимала очень много времени! И, конечно же, рассматриваемый файл был ненужным. Это не было бы проблемой, если бы файл был последним коммитом в основной ветке - в этом случае вы могли бы просто выполнить полный сброс ( git reset --hard HEAD~1 ) и принудительно отправить ветку.

Точно так же, если файл был единственным изменением в данной фиксации, вы могли бы просто удалить всю фиксацию, запустив git reset --hard <commit-id> . Однако в нашем сценарии большой файл был зафиксирован вместе с другим кодом, который мы хотели сохранить в истории, как предпоследняя фиксация.

Как только вы обнаружите проблемный коммит, проверьте его с помощью git checkout и хэша коммита:

 $ git checkout ce861e4c6989a118aade031020fd936bd28d535b Note: checking out 'ce861e4c6989a118aade031020fd936bd28d535b'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new-branch-name> HEAD is now at ce861e4 Add CSS styles

Удалите файл или отредактируйте свой код и оставьте код (или файлы), которые вы хотите сохранить.

 $ rm verylargefile.txt $ git status HEAD detached at ce861e4 Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) deleted: verylargefile.txt no changes added to commit (use "git add" and/or "git commit -a")

Убедитесь, что вы запустили git add -A , чтобы ваш удаленный файл был подготовлен, и Git знал, что его нужно удалить. Теперь запустите git commit --amend -v и Git попросит вас отредактировать сообщение фиксации.

После этого запустите git rebase --onto HEAD <commit-id> main . Здесь вы можете столкнуться с некоторыми конфликтами слияния, что означает конфликт между вашим новым коммитом и старым кодом. Git попросит вас разрешить конфликт:

 $ git add -A $ git status HEAD detached at ce861e4 Changes to be committed: (use "git reset HEAD <file>..." to unstage) deleted: verylargefile.txt $ git commit --amend -v [detached HEAD 7c9516a] Add CSS styles Date: Thu Jan 14 14:43:54 2021 +0100 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 css/common.css.map delete mode 100644 verylargefile.txt $ git status HEAD detached from ce861e4 nothing to commit, working tree clean $ git rebase --onto HEAD ce861e4 First, rewinding head to replay your work on top of it... Fast-forwarded HEAD to HEAD.

Если вы откроете файл в текстовом редакторе, вы увидите, что Git выделил две версии индексного файла. Вам просто нужно удалить один или отредактировать один, чтобы сохранить изменения, которые вам нравятся.

 <p> Toptal was created by engineers. We are entrepreneurs, all passionate about working with top tech talent and exciting companies from all over the world. </p> <<<<<<< HEAD <p> Toptal connects the top 3% of freelance talent all over the world. </p> </main> </body> </html> ======= </main> </body> </html> >>>>>>> Add index file

Код между <<<<<<< HEAD и строкой знаков равенства — это одна версия, а код между знаками равенства и >>>>>>> Add index file — версия из коммита «Добавить индексный файл». . Итак, вы можете видеть, что в одной версии есть дополнительный абзац «Toptal объединяет 3% лучших фрилансеров со всего мира», а в другой нет.

Сохраните отредактированный файл и запустите git add filename , а затем git rebase --continue . Если изменений нет, вы также можете запустить git rebase --skip . Перебазирование может занять некоторое время, если между вашей фиксацией «большого файла» и последней фиксацией на main было много коммитов.

Будьте терпеливы, и если вы работаете в большой команде, обязательно получите второе мнение! Особенно важно по возможности проконсультироваться с человеком(ами), который написал(и) коммит(ы), который(е) вы объединяете.

Помните, что изменения слияния относятся к конкретному коммиту в истории, а не к вашим последним изменениям. То есть, если вы редактируете фиксацию, когда текст на вашем сайте был Arial, а теперь это Verdana, вы все равно должны сохранить эту фиксацию с историей Arial в качестве шрифта.

Также обратите внимание, что если Git увидит пробел или символ конца строки, это может вызвать конфликт слияния, поэтому будьте осторожны!

Больше, чем просто зафиксировать и потянуть

Git мощнее, чем думают многие разработчики. Если вы представляете новичка, обязательно дайте ему несколько советов об этих бесценных функциях. Это делает рабочий процесс более эффективным.

Хотите узнать больше о Git? Взгляните на страницу Toptal Git Tips and Practices.