Разное

Удалить из коммита файл git: git — Как удалить один файл из последнего коммита

Содержание

Как в Git убрать файл из подготовки в коммиту?

Deprecated: Function create_function() is deprecated in /home/worldhel/public_html/wp-content/plugins/codecolorer/lib/geshi.php on line 4698

Принято считать, что файл в репозитории, находящемся под версионным контролем SCV GIT, может находится в одном из 4 состояний:

  • Неотслеживаемый Untracked
  • Отслеживаемый неизмененный Tracked unmodified
  • Отслеживаемый с изменениями Tracked modified
  • Отслеживаемый подготовленный для фиксации в коммит Tracked staged

Файл со статусом staged — это файл который находится под версионным контролем, в который были внесены изменения, и эти изменения в файле были подготовлены для фиксации в следующем коммите командой git add .

Следующим логическим шагом является фиксация таких файлов staged в коммит с помощью команды $ git commit -m "Комментарий к коммиту", но что если Вы захотите один из файлов пока что не включать в следующий коммит?

Для этого нужно перевести файл из состояния tracked staged в состояние tracked modified. Это значит, что git продолжает осуществлять контроль над всеми сделанными в этом файле изменениями, просто файл не будет добавлен в следующий коммит.

Делается это очень просто при помощи команды:

1

$ git reset HEAD имя_файла

Рассмотрим все вышесказанное на наглядном примере. У нас есть каталог с тремя измененными файлами, если выполним команду $ git status, то узнаем состояние репозитория.

Состояние репозитория. Имеются изменения в 3 файлах.

Допустим, что в следующий коммит мы решили добавить все 3 файла с расширением php, и вначале мы добавляем файлы для фиксации в коммит, командой:

Теперь если мы посмотрим статус файлов в репозитории, то увидим, что эти 3 файла теперь в состоянии staged и готовы к фиксации в коммит.

Файлы в состоянии staged.

По каким-то причинам, мы посчитали, что один файл third.php рано включать в следующий коммит, например не подходит под общую логику коммита, и будет включен в более поздний. Тогда воспользуемся коммандой, которая сбросит статус файла на изначальное:

1

$ git reset HEAD third.php

Результат работы команды git reset HEAD.

Теперь если сделать коммит изменений, то в него войдут только желаемые файлы.

1

$ git commit -m «Текст коммита»

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

1
2

$ git log -2
$git status

В качестве резюме отметим, что если файл по ошибке переведен в статус staged, в системе контроля версий GIT очень удобно и быстро перевести в его в предыдущий статус при помощи команды git reset HEAD.

Добавление, удаление и переименование файлов в репозитории

В рамках данного урока рассмотрим вопросы, касающиеся добавления, удаления и переименования файлов в git репозитории.

Добавление файлов в git репозиторий

Добавление файлов в репозиторий – это достаточно простая операция, мало чем отличающаяся от отправки изменений в отслеживаемых файлах в репозиторий. Мы уже не раз выполняли эту операцию в предыдущих уроках, но сделаем это ещё раз. Создадим новый репозиторий, для этого перейдите в каталог, в котором вы хотите его расположить и введите команду git init.

> git init

Создайте в каталоге файл README.md любым удобным для вас способом, мы сделаем это с помощью команды touch.

> touch README.md

Теперь проверим состояние отслеживаемой директории.

> git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        README.md

nothing added to commit but untracked files present (use "git add" to track)

Как вы можете видеть: в рабочей директории есть один неотслеживаемый файл README.md. Git нам подсказывает, что нужно сделать для того, чтобы начать отслеживать изменения в файле README.md: необходимо выполнить команду git add, сделаем это.

> git add README.md

Посмотрим ещё раз на состояние.

> git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   README.md

Видно, что информация о появлении нового файла попала в stage. Для того чтобы это изменение зафиксировалось в репозитории необходимо выполнить команду git commit.

> git commit -m "add README.md file"
[master (root-commit) 0bb6c94] add README.md file
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README.md

Теперь в рабочей директории и в stage нет объектов, информацию об изменении которых необходимо внести в репозиторий.

> git status
On branch master
nothing to commit, working tree clean

В репозиторий был сделан один коммит.

> git log --oneline
0bb6c94 add README.md file

Удаление файлов из git репозитория и из stage

Удаление файла из stage

Вначале разберемся со stage. Создадим ещё один файл.

> touch main.c

“Отправим” файл main.c в stage.

> git add main.c

Внесем изменения в README.md.

> echo "# README" > README.md

Информацию об этом также отправим в stage.

> git add README.md

Посмотрим на состояние stage.

> git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   README.md
        new file:   main.c

Если нам необходимо убрать из stage, какой-то из этих файлов (main.c или README.md), то для этого можно воспользоваться командой git –rm cashed <filename>, сделаем это для файла main.c.

> git rm --cached main.c
rm 'main.c'

Теперь посмотрим на состояние рабочей директории и stage.

> git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   README.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        main.c

Видно, что изменения в файле README.md готовы для коммита, а вот файл main.c перешел в состояние – неотслеживаемый. Отправим main.c в stage и, после этого, сделаем коммит в репозиторий.

> git add main.c
> git commit -m "add main.c and do some changes in README.md"
[master 49049bc] add main.c and do some changes in README.md
 2 files changed, 1 insertion(+)
 create mode 100644 main.c

Удаление файлов из git репозитория

Удалить файл из репозитория можно двумя способами: первый – удалить его из рабочей директории и уведомить об этом git; второй – воспользоваться средствами git. Начнем с первого способа. Для начала посмотрим, какие файлы у нас хранятся в репозитории.

> git ls-tree master
100644 blob 7e59600739c96546163833214c36459e324bad0a    README.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    main.c

Удалим файл main.c из рабочей директории.

> rm main.c
> ls
README.md

Уведомим об этом систему git.

> git rm main.c
rm 'main.c'

Вместо команды git rm можно использовать git add, но само слово add в данном случае будет звучать несколько неоднозначно, поэтому лучше использовать rm. На данном этапе еще можно вернуть все назад с помощью команды git checkout — <filename>, в результате, в нашу рабочую директорию будет скопирован файл из репозитория. Создадим коммит, фиксирующий удаление файла.

> git commit -m "remove main.c"
[master d4e22ae] remove main.c
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 main.c

Теперь в репозитории остался только один файл README.md.

> git ls-tree master
100644 blob 7e59600739c96546163833214c36459e324bad0a    README.md

Второй способ – это сразу использовать команду git rm без предварительного удаления файла из директории. Вновь создадим файл main.c и добавим его в репозиторий.

> touch main.c
> git add main.c
> git commit -m "add main.c file"
[master 6d93049] add main.c file
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 main.c
> git ls-tree master
100644 blob 7e59600739c96546163833214c36459e324bad0a    README.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    main.c

Удалим файл из репозитория.

> git rm main.c
rm 'main.c'

> git commit -m "deleted: main.c file"
[master ba7d027] deleted: main.c file
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 main.c

Файла main.c больше нет в репозитории.

> git ls-tree master
100644 blob 7e59600739c96546163833214c36459e324bad0a    README.md

Его также нет и в рабочем каталоге.

> ls
README.md

Удалите файл README.md из репозитория самостоятельно.

Переименование файлов в git репозитории

Как и в случае с удалением, переименовать файл в git репозитории можно двумя способами – с использованием и без использования средств операционной системы.

Первый способ. Создадим файл test_main_file.c и добавим его в репозиторий.

> touch test_main_file.c

> git add test_main_file.c

> git commit -m "add test_main_file.c"
[master 6cf53ac] add test_main_file.c
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test_main_file.c

Содержимое репозитория после этого будет выглядеть так.

> git ls-tree master
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    test_main_file.c

Переименуем его на test_main.c.

Сделаем это в рабочей директории.

> mv test_main_file.c test_main.c

Теперь отправим изменение в репозиторий.

> git add .
> git commit -m "Rename test_main_file.c"
[master 79528c4] Rename test_main_file.c
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename test_main_file.c => test_main.c (100%)

В репозитории и в рабочей директории будет находится только файл test_main.c.

> git ls-tree master
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    test_main.c

> ls
test_main.c

Второй способ.

В рамках второго способа рассмотрим работу с командой git mv. Переименуем файл test_main.c в main.c. Текущее содержимое репозитория и рабочего каталога.

> git ls-tree master
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    test_main.c
> ls
test_main.c

Переименуем файл test_main.c на main.c средствами git.

> git mv test_main.c main.c

> git commit -m "Rename test_main.c file"
[master c566f0e] Rename test_main.c file
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename test_main.c => main.c (100%)

Имя файла изменилось как в репозитории так и в рабочем каталоге.

> git ls-tree master
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    main.c

> ls
main.c

Отличный курс по git  делают ребята из GeekBrains, найдите в разделе “Курсы” курс “Git. Быстрый старт”, он бесплатный!

<<<Часть 7. Поговорим о HEAD и tree-ish   Часть 9. Как удалить коммит в git?>>>

Работа с Git репозиторием. Команды: создать ветку, удалить коммит,

Обновлено: 14.04.2019 г.

В данном разделе мы собрали решение типовых задач, которые могут вам при работе с git репозиторием. В своих проектах мы используем обычную сборку git и GitLab. Поэтому в данных примерах могут быть примеры описанные при работе с данными программами.

Генерация и настройка ключей git для деплоя

  1. Для того чтобы сгенерировать deploy key, нужно подключиться к серверу по ssh. Затем выполнить команду ssh-keygen.
  2. В консоли появится диалог, в котором нужно будет ввести название файла, где будет сохранен ключ. Этот шаг можно пропустить, тогда ключ будет сохранен в файл с именем по умолчанию (id_rsa).
  3. После этого будет предложено ввести кодовую фразу для дополнительной защиты, этот шаг можно пропустить (чтобы не вводить фразу каждый раз, когда идет обращение к гиту).
  4. После этого ключ будет сгенерирован, и будет создано 2 файла с приватным и публичным ключами.Теперь нужно лишь скопировать публичный ключ и добавить его в гит репозиторий. Выполняем команду cd ~/.ssh и переходим в директорию, где сохранен наш ключ. Для того чтобы вывести его в консоль, выполняем команду cat <имя файла> (по умолчанию id_rsa.pub). ОБратите внимание, что нужен именно файл с расширением .pub (публичный ключ). Копируем содержимое файла.
  5. Далее в GitLab можно настроить репозитория.
    1. А в разделе настроек выбрать пункт Deploy keys.
    2. Далее нажимаем “New Deploy Key” и попадаем в форму создания нового ключа. Вставляем ключ в поле Key, заполняем название (Title) ключа (в названии желательно указать имя пользователя и ip сервера, где был сгенерирован ключ).

Обновление проекта на git с сервера

Данная действие требуется, когда на сервере, где установлен проект, вносились правки напрямую (например, через sftp или ssh, а не через git).
Для обновления необходимо проделать следующие операции:

  1. Подключиться к серверу, на котором уже развернут проект, подключение производим через SSH.
  2. Убедиться, что мы находимся в нужной ветке, для этого вводим команду — “git branch”. Мы находимся в ветке “master”.
  3. Далее вводим команду — “git status”.
  4. Далее нужно убедиться в том, что есть изменения в файлах. Обычно Git помечает их красным цветом.
  5. Эти файлы необходимо добавить к индексируемым, следовательно вводим команду — “git add .” “Точка” говорит нам о том, что будут добавлены все файлы. Либо можно добавлять файлы через пробел “git add file1.php file2.php”.
  6. Снова проверяем статус репозитория “git status”, добавленные файлы должны быть быть отмечены зеленым цветом.
  7. Затем можно создать коммит — “git commit -m ‘your message here’”.
  8. Далее делаем “git pull origin master”, принимаем изменения из удаленного репозитория той ветки, в которой находимся.
  9. Далее отправляем наши изменения той ветки, в которой находимся — “git push origin master”.
  10. Проверяем статус локального репозитория — “git status”, в ответ получаем “On branch master. nothing to commit, working directory clean”.

Какие ветки создавать на новые проекты

Для работы над новым проектом по умолчанию git создаёт ветку master. Если у проекта будет 2 версии (тестовая и боевая), то вам перед началом разработки необходимо создать новую ветку — dev. Для этого нужно:

  1. Либо создать ветку с именем dev, локально выполнив команду “git checkout -b dev” находясь в ветке master;
  2. Либо создать новую верстку в репозитории посредством GitLab: Project — Branches — New Branch.

Как залить обновления на сервер с git

Если проект имеет только боевую версию (prod):

  1. Подключаемся по ssh (вводим логин, пароль, хост).
  2. Переходим в директорию с проектом cd (обычно cd var/www/site.ru — если не знаете, то уточните у Менеджера).
  3. Выполняем команду “git pull”.

Если проект имеет 2 версии: dev (тестовую версию) и prod (боевой проект)

Если у нас используется 2 версии проекта, то обновления заливаются в 2 ветки: dev и prod.

  1. Для выгрузки обновления подключаемся по ssh (вводим логин, пароль, хост).
  2. Переходим в директорию с тестовым или боевым проектом cd (обычно cd var/www/dev.site.ru или var/www/site.ru — если не знаете, то уточните у Менеджера).
  3. Далее проверяем, что мы находимся в dev ветке, для этого выполняем команду git branch, в результате получаем master или dev (если увидели не то, то выполняем команду для переключения в нужную ветку “git checkout <ветка>”).
  4. Если вы находитесь в нужной ветке, то выполняете “git pull”.

Как откатить коммит?

Если требуется отменить изменения в уже созданном коммите, допустим, вы что-то забыли дописать в коде, то нужно выполнить:

  1. Внимание! Данная операция не затронет внесённых изменений.
  2. Выполняем команду “git reset —soft HEAD^”.
  3. Отменяется последний коммит, далее мы вносим изменения в коде.
  4. Далее создаем новый коммит командой “git commit -m ‘add some code’ ”.
  5. И отправляем изменения в репозиторий командой “git push origin master”.

Если требуется откатить залитые правки до предыдущего коммита, то нужно выполнить:

  1. Осторожно! Эта команда безвозвратно удаляет несохраненные текущие изменения.
  2. Для начала нужно узнать хэш последнего коммита. Для этого выполняем команду “git show-ref —heads —hash master”.
  3. Далее вводим команду “git revert e882466”, где e882466 — первые 7 символов хэша текущего коммита.
  4. Далее нужно подтвердить откат коммита. Нужно ввести название коммита или оставить уже введенный автоматически текст Revert “add one more object” (это пример).
  5. Далее отправляем коммит в репозиторий командой “git push origin master” (если текущая ветка master).

Как перенести новый проект клиента в свой git?

В том случае, если проект редактировался напрямую через ftp или ssh, то требуется обновить версию проекта, размещенного на git. Для этого необходимо выполнить следующие шаги:

  1. Необходимо получить исходные файлы проекта, путем скачивания через FTP-клиент на свой компьютер.
  2. Необходимо получить базу данных проекта. Обычно выкачивается через через PhpMyAdmin, через SSH командой mysqldump или с помощью поддержки системного администратора (можно уточнить у Менеджера).
  3. Далее нужно сообщить Менеджеру, чтобы он создал новый репозиторий в GitLab для данного проекта.
  4. Далее клонируем пустой репозиторий к себе на локальный компьютер, например, в папку C:\Projects\foobar с помощью команды ‘git clone полный-путь-до-репозитория.git ’.
  5. Скачанный проект нужно поместить в папку с клонированным пустым репозиторием (который находится, например, в папке C:\Projects\foobar).
  6. Создать файл .gitignore и указать там необходимые файлы и директории, которые не должны попасть в git.
  7. Далее нужно отправить в гит файлы проекта, выполнив команду “git push origin master”.
  8. Далее нужно запросить у Менеджера доступный для это проекта домен (или поддомен) для разработки, а также доступы к SSH сервера, доступы для подключения к СУБД и выделенную базу данных для этого проекта, на котором будет вестись доработка проекта или обычное расположение.
  9. Необходимо зайти на сервер под полученными доступами SSH
  10. Начать развертывание проекта из git.
    1. Перейти в указанную Менеджером папку с поддоменом с помощью команды cd (обычно cd var/www/site.ru).
    2. Сгенерировать и настроить deploy keys (см. пункт 1).
    3. Выполнить команду ‘git clone полный-путь-до-репозитория.git ’.
    4. Заказать на сервер дамп базы данных с помощью команды scp с указанием размещения на сервере пути для дампа БД (она похожа на команду ssh).
    5. Развернуть дамп БД на сервере выполнить mysql -u USER -pPASSWORD DATABASE < /path/to/dump.sql.
    6. Если проект основан на фреймворке (Yii2, Symfony ¾, Laravel, Zend или другой), то необходимо подтянуть зависимости PHP пакетов (расширений).
    7. Нужно установить composer.phar в папку проекта, выполнив команды, указанные по этому адресу https://getcomposer.org/download/.
    8. Выполнить команду composer.phar update.
    9. Загрузить файлы и директории, которые ранее добавили в .gitignore.
    10. Проверить работоспособность проекта, пройдя по поддомену/домену.

Отправка проекта в Git, если будет выполнятся code review

Code review — процесс проверки кода на предмет технических не соответсвий и ошибок.
Для удобного просмотра изменений бновления нужно вгрузить в ветку master через Merge Request (не путать с консольной командой merge) в панели управления репозиторием GitLab.
Для этого выполните следующие действия:

  1. В разделе Merge Requests в панели управления репозиторием GitLab перейти в раздел “New Merge Request”.
  2. Далее в качестве Source branch выбрать ветку dev, а в качестве Target branch соответственно master ветку.
  3. После нажатия на кнопку Compage branches and continue отобразится следующая форма:

    В качестве Title необходимо указать ID и наименование задачи из багтрекера, а также необходимо закрепить merge request за проверяющим порграммистом выбрав его в поле Assignee.

После того как проверяющий проверил реализованный код, то необходимо произвести git pull на сервере в продакшн версии проекта.

Шпаргалка по консольным командам Git

Общее

Git — система контроля версий (файлов). Что-то вроде возможности сохраняться в компьютерных играх (в Git эквивалент игрового сохранения — коммит). Важно: добавление файлов к «сохранению» двухступенчатое: сначала добавляем файл в индекс (git add), потом «сохраняем» (git commit).

Любой файл в директории существующего репозитория может находиться или не находиться под версионным контролем (отслеживаемые и неотслеживаемые).

Отслеживаемые файлы могут быть в 3-х состояниях: неизменённые, изменённые, проиндексированные (готовые к коммиту).

Концепция GIT

Ключ к пониманию концепции git — знание о «трех деревьях»:

  • Рабочая директория — файловая система проекта (те файлы, с которыми вы работаете).
  • Индекс — список отслеживаемых git-ом файлов и директорий, промежуточное хранилище изменений (редактирование, удаление отслеживаемых файлов).
  • Директория .git/ — все данные контроля версий этого проекта (вся история разработки: коммиты, ветки, теги и пр.).

Коммит — «сохранение» (хранит набор изменений, сделанный в рабочей директории с момента предыдущего коммита). Коммит неизменен, его нельзя отредактировать.

У всех коммитов (кроме самого первого) есть один или более родительских коммитов, поскольку коммиты хранят изменения от предыдущих состояний.

Простейший цикл работ

  • Редактирование, добавление, удаление файлов (собственно, работа).
  • Индексация/добавление файлов в индекс (указание для git какие изменения нужно будет закоммитить).
  • Коммит (фиксация изменений).
  • Возврат к шагу 1 или отход ко сну.

Указатели

  • HEAD — указатель на текущий коммит или на текущую ветку (то есть, в любом случае, на коммит). Указывает на родителя коммита, который будет создан следующим.
  • ORIG_HEAD — указатель на коммит, с которого вы только что переместили HEAD (командой git reset ..., например).
  • Ветка (master, develop etc.) — указатель на коммит. При добавлении коммита, указатель ветки перемещается с родительского коммита на новый.
  • Теги — простые указатели на коммиты. Не перемещаются.

Настройки

Перед началом работы нужно выполнить некоторые настройки:

git config --global user.name "Your Name" # указать имя, которым будут подписаны коммиты
git config --global user.email "[email protected]"  # указать электропочту, которая будет в описании коммитера

Если вы в Windows:

git config --global core.autocrlf true # включить преобразование окончаний строк из CRLF в LF

Указание неотслеживаемых файлов3>

Файлы и директории, которые не нужно включать в репозиторий, указываются в файле .gitignore. Обычно это устанавливаемые зависимости (node_modules/, bower_components/), готовая сборка build/ или dist/ и подобные, создаваемые при установке или запуске. Каждый файл или директория указываются с новой строки, возможно использование шаблонов.

Консоль

Как использовать консоль Bash в Windows, основные команды.

Длинный вывод в консоли: Vim

Вызов некоторых консольных команд приводит к необходимости очень длинного вывода в консоль (пример: вывод истории всех изменений в файле командой git log -p fileName.txt). При этом прямо в консоли запускается редактор Vim. Он работает в нескольких режимах, из которых Вас заинтересуют режим вставки (редактирование текста) и нормальный (командный) режим. Чтобы попасть из Vim обратно в консоль, нужно в командном режиме ввести :q. Переход в командный режим из любого другого: Esc.

Если нужно что-то написать, нажмите i — это переход в режим вставки текста. Если нужно сохранить изменения, перейдите в командный режим и наберите :w.

Vim (некоторые команды)

# Нажатия кнопок
ESC     — переход в командный режим
i       — переход в режим редактирования текста
ZQ (зажат Shift, поочередное нажатие) — выход без сохранения
ZZ (зажат Shift, поочередное нажатие) — сохранить и выйти
```bash
# Нажатия кнопок
ESC     — переход в командный режим
i       — переход в режим редактирования текста
ZQ (зажат Shift, поочередное нажатие) — выход без сохранения
ZZ (зажат Shift, поочередное нажатие) — сохранить и выйти

# Ввод в командном режиме
:q!             — выйти без сохранения
:wq             — сохранить файл и выйти
:w filename.txt — сохранить файл как filename.txt

Консольные команды

Создать новый репозиторий

git init             # создать новый проект в текущей директории
git init folder-name # создать новый проект в указанной директории

Клонирование репозитория

# клонировать удаленный репозиторий в одноименную директорию
git clone https://github.com/cyberspacedk/Git-commands.git    

# клонировать удаленный репозиторий в директорию «FolderName»
git clone https://github.com/cyberspacedk/Git-commands.git FolderName 

# клонировать репозиторий в текущую директорию
git clone https://github.com:nicothin/web-design.git .           

Просмотр изменений

git status              # показать состояние репозитория (отслеживаемые, изменённые, новые файлы и пр.)
git diff                # сравнить рабочую директорию и индекс (неотслеживаемые файлы ИГНОРИРУЮТСЯ)
git diff --color-words  # сравнить рабочую директорию и индекс, показать отличия в словах (неотслеживаемые файлы ИГНОРИРУЮТСЯ)
git diff index.html     # сравнить файл из рабочей директории и индекс
git diff HEAD           # сравнить рабочую директорию и коммит, на который указывает HEAD (неотслеживаемые файлы ИГНОРИРУЮТСЯ)
git diff --staged       # сравнить индекс и коммит с HEAD
git diff master feature # посмотреть что сделано в ветке feature по сравнению с веткой master
git diff --name-only master feature # посмотреть что сделано в ветке feature по сравнению с веткой master, показать только имена файлов
git diff master...feature # посмотреть что сделано в ветке feature с момента (коммита) расхождения с master

Добавление изменений в индекс

git add .        # добавить в индекс все новые, изменённые, удалённые файлы из текущей директории и её поддиректорий
git add text.txt # добавить в индекс указанный файл (был изменён, был удалён или это новый файл)
git add -i       # запустить интерактивную оболочку для добавления в индекс только выбранных файлов
git add -p       # показать новые/изменённые файлы по очереди с указанием их изменений и вопросом об отслеживании/индексировании

Удаление изменений из индекса

git reset            # убрать из индекса все добавленные в него изменения (в рабочей директории все изменения сохранятся), антипод git add
git reset readme.txt # убрать из индекса изменения указанного файла (в рабочей директории изменения сохранятся)

Отмена изменений

git checkout text.txt      # ОПАСНО: отменить изменения в файле, вернуть состояние файла, имеющееся в индексе
git reset --hard           # ОПАСНО: отменить изменения; вернуть то, что в коммите, на который указывает HEAD (незакомиченные изменения удалены из индекса и из рабочей директории, неотслеживаемые файлы останутся на месте)
git clean -df              # удалить неотслеживаемые файлы и директории

Коммиты

git commit -m "Name of commit"    # зафиксировать в коммите проиндексированные изменения (закоммитить), добавить сообщение
git commit -a -m "Name of commit" # проиндексировать отслеживаемые файлы (ТОЛЬКО отслеживаемые, но НЕ новые файлы) и закоммитить, добавить сообщение

Отмена коммитов и перемещение по истории

Все коммиты, которые уже были отправлены в удалённый репозиторий, должны отменяться новыми коммитами (git revert), дабы избежать проблем с историей разработки у других участников проекта.

git revert HEAD --no-edit    # создать новый коммит, отменяющий изменения последнего коммита без запуска редактора сообщения
git revert b9533bb --no-edit # то же, но отменяются изменения, внесённые коммитом с указанным хешем (b9533bb)

Все команды, приведённые ниже можно выполнять ТОЛЬКО если коммиты еще не были отправлены в удалённый репозиторий.

# ВНИМАНИЕ! Опасные команды, можно потерять незакоммиченные изменения
git commit --amend -m "Название"  # «перекоммитить» изменения последнего коммита, заменить его новым коммитом с другим сообщением (сдвинуть текущую ветку на один коммит назад, сохранив рабочую директорию и индекс «как есть», создать новый коммит с данными из «отменяемого» коммита, но новым сообщением)
git reset --hard @~      # передвинуть HEAD (и ветку) на предыдущий коммит, рабочую директорию и индекс сделать такими, какими они были в момент предыдущего коммита
git reset --hard 75e2d51 # передвинуть HEAD (и ветку) на коммит с указанным хешем, рабочую директорию и индекс сделать такими, какими они были в момент указанного коммита
git reset --soft @~      # передвинуть HEAD (и ветку) на предыдущий коммит, но в рабочей директории и индексе оставить все изменения
git reset --soft @~2     # то же, но передвинуть HEAD (и ветку) на 2 коммита назад
git reset @~             # передвинуть HEAD (и ветку) на предыдущий коммит, рабочую директорию оставить как есть, индекс сделать таким, каким он был в момент предыдущего коммита (удобнее, чем git reset --soft @~, если индекс нужно задать заново)
# Почти как git reset --hard, но безопаснее: не получится потерять изменения в рабочей директории
git reset --keep @~      # передвинуть HEAD (и ветку) на предыдущий коммит, сбросить индекс, но в рабочей директории оставить изменения, если возможно (если файл с изменениями между коммитами менялся, будет выдана ошибка и переключение не произойдёт)

Временно переключиться на другой коммит

git checkout b9533bb # переключиться на коммит с указанным хешем (переместить HEAD на указанный коммит, рабочую директорию вернуть к состоянию, на момент этого коммита)
git checkout master  # переключиться на коммит, на который указывает master (переместить HEAD на коммит, на который указывает master, рабочую директорию вернуть к состоянию на момент этого коммита)

Переключиться на другой коммит и продолжить работу с него

Потребуется создание новой ветки, начинающейся с указанного коммита.

git checkout -b new-branch 5589877   # создать ветку new-branch, начинающуюся с коммита c хешем 5589877 (переместить HEAD на указанный коммит, рабочую директорию вернуть к состоянию, на момент этого коммита, создать указатель на этот коммит (ветку) с указанным именем)

Восстановление изменений

git checkout 5589877 index.html  # восстановить в рабочей директории указанный файл на момент указанного коммита (и добавить это изменение в индекс) (git reset index.html для удаления из индекса, но сохранения изменений в файле)

Копирование коммита (перенос коммитов)

git cherry-pick 5589877          # скопировать на активную ветку изменения из указанного коммита, закоммитить эти изменения
git cherry-pick master~2..master # скопировать на активную ветку изменения из master (2 последних коммита)
git cherry-pick -n 5589877       # скопировать на активную ветку изменения из указанного коммита, но НЕ КОММИТИТЬ (подразумевается, что мы сами потом закоммитим)
git cherry-pick master..feature  # скопировать на активную ветку изменения из всех коммитов ветки feature с момента её расхождения с master (похоже на слияние веток, но это копирование изменений, а не слияние), закоммитить эти изменения; это может вызвать конфликт
git cherry-pick --abort    # прервать конфликтный перенос коммитов
git cherry-pick --continue # продолжить конфликтный перенос коммитов (сработает только после решения конфликта)

Удаление файла

git rm text.txt    # удалить отслеживаемый неизменённый файл и проиндексировать это изменение
git rm -f text.txt # удалить отслеживаемый изменённый файл и проиндексировать это изменение
git rm -r log/     # удалить всё содержимое отслеживаемой директории log/ и проиндексировать это изменение
git rm ind*        # удалить все отслеживаемые файлы с именем, начинающимся на «ind» в текущей директории и проиндексировать это изменение
git rm --cached readme.txt # удалить из отслеживаемых индексированный файл (ФАЙЛ ОСТАНЕТСЯ НА МЕСТЕ) (часто используется для нечаянно добавленных в отслеживаемые файлов)

Перемещение/переименование файлов

Для git не существует переименования. Переименование воспринимается как удаление старого файла и создание нового. Факт переименования может быть определен только после индексации изменения.

git mv text.txt test_new.txt # переименовать файл «text.txt» в «test_new.txt» и проиндексировать это изменение
git mv readme_new.md folder/ # переместить файл readme_new.md в директорию folder/ (должна существовать) и проиндексировать это изменение

История коммитов

Выход из длинного лога вывода: q.

git log master             # показать коммиты в указанной ветке
git log -2                 # показать последние 2 коммита в активной ветке
git log -2 --stat          # показать последние 2 коммита и статистику внесенных ими изменений
git log -p -22             # показать последние 22 коммита и внесенную ими разницу на уровне строк
git log --graph -10        # показать последние 10 коммитов с ASCII-представлением ветвления
git log --since=2.weeks    # показать коммиты за последние 2 недели
git log --after '2018-06-30' # показать коммиты, сделанные после указанной даты
git log index.html         # показать историю изменений файла index.html (только коммиты)
git log -5 index.html      # показать историю изменений файла index.html, последние 5 коммитов (только коммиты)
git log -p index.html      # показать историю изменений файла index.html (коммиты и изменения)
git log -G'myFunction' -p  # показать все коммиты, в которых менялись строки с myFunction (в кавычках регулярное выражение)
git log -L '//','//':index.html # показать изменения от указанного до указанного регулярных выражений в указанном файле
git log --grep fix         # показать коммиты, в описании которых есть буквосочетание fix (регистрозависимо, только коммиты текущей ветки)
git log --grep fix -i      # показать коммиты, в описании которых есть буквосочетание fix (регистроНЕзависимо, только коммиты текущей ветки)
git log --grep 'fix(ing|me)' -P # показать коммиты, в описании которых есть совпадения для регулярного выражения (только коммиты текущей ветки)
git log --pretty=format:"%h - %an, %ar : %s" -4 # показать последние 4 коммита с форматированием выводимых данных
git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short # мой формат вывода, висящий на алиасе оболочки
git log master..branch_99  # показать коммиты из ветки branch_99, которые не влиты в master
git log branch_99..master  # показать коммиты из ветки master, которые не влиты в branch_99
git log master...branch_99 --boundary -- graph # показать коммиты из указанных веток, начиная с их расхождения (коммит расхождения будет показан)
git show 60d6582           # показать изменения из коммита с указанным хешем
git show HEAD~             # показать данные о предыдущем коммите в активной ветке
git show @~                # аналогично предыдущему
git show HEAD~3            # показать данные о коммите, который был 3 коммита назад
git show my_branch~2       # показать данные о коммите, который был 2 коммита назад в указанной ветке
git show @~:index.html     # показать контент указанного файла на момент предыдущего (от HEAD) коммита
git show :/"подвал"        # показать самый новый коммит, в описании которого есть указанное слово (из любой ветки)

Кто написал строку

git blame README.md --date=short -L 5,8 # показать строки 5-8 указанного файла и коммиты, в которых строки были добавлены

История изменений указателей (веток, HEAD)

git reflog -20             # показать последние 20 изменений положения указателя HEAD
git reflog --format='%C(auto)%h %

Ветки

git branch                 # показать список веток
git branch -v              # показать список веток и последний коммит в каждой
git branch new_branch      # создать новую ветку с указанным именем на текущем коммите
git branch new_branch 5589877 # создать новую ветку с указанным именем на указанном коммите
git branch -f master 5589877  # переместить ветку master на указанный коммит
git branch -f master master~2 # переместить ветку master на 2 коммита назад
git checkout new_branch    # перейти в указанную ветку
git checkout -b new_branch # создать новую ветку с указанным именем и перейти в неё
git checkout -B master 5589877 # переместить ветку с указанным именем на указанный коммит и перейти в неё
git merge hotfix           # влить в ветку, в которой находимся, данные из ветки hotfix
git merge hotfix -m "Горячая правка" # влить в ветку, в которой находимся, данные из ветки hotfix (указано сообщение коммита слияния)
git merge hotfix --log     # влить в ветку, в которой находимся, данные из ветки hotfix, показать редактор описания коммита, добавить в него сообщения вливаемых коммитов
git merge hotfix --no-ff   # влить в ветку, в которой находимся, данные из ветки hotfix, запретить простой сдвиг указателя, изменения из hotfix «останутся» в ней, а в активной ветке появится только коммит слияния
git branch -d hotfix       # удалить ветку hotfix (используется, если её изменения уже влиты в главную ветку)
git branch --merged        # показать ветки, уже слитые с активной
git branch --no-merged     # показать ветки, не слитые с активной
git branch -a              # показать все имеющиеся ветки (в т.ч. на удаленных репозиториях)
git branch -m old_branch_name new_branch_name # переименовать локально ветку old_branch_name в new_branch_name
git branch -m new_branch_name # переименовать локально ТЕКУЩУЮ ветку в new_branch_name
git push origin :old_branch_name new_branch_name # применить переименование в удаленном репозитории
git branch --unset-upstream # завершить процесс переименования

Теги

git tag v1.0.0               # создать тег с указанным именем на коммите, на который указывает HEAD
git tag -a -m 'В продакшен!' v1.0.1 master # создать тег с описанием на том коммите, на который смотрит ветка master
git tag -d v1.0.0            # удалить тег с указанным именем(ами)
git tag -n                   # показать все теги, и по 1 строке сообщения коммитов, на которые они указывают
git tag -n -l 'v1.*'         # показать все теги, которые начинаются с 'v1.*'

Временное сохранение изменений без коммита

git stash     # временно сохранить незакоммиченные изменения и убрать их из рабочей директории
git stash pop # вернуть сохраненные командой git stash изменения в рабочую директорию

Удалённые репозитории

Есть два распространённых способа привязать удалённый репозиторий к локальному: по HTTPS и по SSH. Если SSH у вас не настроен (или вы не знаете что это), привязывайте удалённый репозиторий по HTTPS (адрес привязываемого репозитория должен начинаться с https://).

git remote -v              # показать список удалённых репозиториев, связанных с локальным
git remote remove origin   # убрать привязку удалённого репозитория с сокр. именем origin
git remote add origin https://github.com:nicothin/test.git # добавить удалённый репозиторий (с сокр. именем origin) с указанным URL
git remote rm origin       # удалить привязку удалённого репозитория
git remote show origin     # получить данные об удалённом репозитории с сокращенным именем origin
git fetch origin           # скачать все ветки с удаленного репозитория (с сокр. именем origin), но не сливать со своими ветками
git fetch origin master    # то же, но скачивается только указанная ветка
git checkout --track origin/github_branch # создать локальную ветку github_branch (данные взять из удалённого репозитория с сокр. именем origin, ветка github_branch) и переключиться на неё
git push origin master     # отправить в удалённый репозиторий (с сокр. именем origin) данные своей ветки master
git pull origin            # влить изменения с удалённого репозитория (все ветки)
git pull origin master     # влить изменения с удалённого репозитория (только указанная ветка)

Конфликт слияния

Предполагается ситуация: есть ветка master и есть ветка feature. В обеих ветках есть коммиты, сделанные после расхождения веток. В ветку master пытаемся влить ветку feature (git merge feature), получаем конфликт, т.к. в обеих ветках есть изменения одной и той же строки в файле index.html.

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

git merge feature                # влить в активную ветку изменения из ветки feature
git merge-base master feature    # показать хеш последнего общего коммита для двух указанных веток
git checkout --ours index.html   # оставить в конфликтном файле (index.html) состояние ветки, В КОТОРУЮ мы вливаем (в примере — из ветки master)
git checkout --theirs index.html # оставить в конфликтном файле (index.html) состояние ветки, ИЗ КОТОРОЙ мы вливаем (в примере — из ветки feature)
git checkout --merge index.html  # показать в конфликтном файле (index.html) сравнение содержимого сливаемых веток (для ручного редактирования)
git checkout --conflict=diff3  --merge index.html # показать в конфликтном файле (index.html) сравнение содержимого сливаемых веток плюс то, что было в месте конфликта в коммите, на котором разошлись сливаемые ветки
git reset --hard  # прекратить это прерванное слияние, вернуть рабочую директорию и индекс как было в момент коммита, на который указывает HEAD, а я пойду немного поплачу
git reset --merge # прекратить это прерванное слияние, но оставить изменения, не закоммиченные до слияния (для случая, когда слияние делается не на чистом статусе)
git reset --abort # то же, что и строкой выше

«Перенос» ветки

Можно «переместить» ответвление какой-либо ветки от основной на произвольный коммит. Это нужно для того, чтобы в «переносимой» ветке появились какие-либо изменения, внесённые в основной ветке (уже после ответвления переносимой).

Нельзя «переносить» ветку, если она уже отправлена на удалённый репозиторий.

git rebase master # перенести все коммиты (создать их копии) активной ветки так, будто активная ветка ответвилась от master на нынешней вершине master (часто вызывает конфликты)
git rebase --onto master feature # перенести коммиты активной ветки на master, начиная с того места, в котором активная ветка отделилась от ветки feature
git rebase --abort # прервать конфликтный rebase, вернуть рабочую директорию и индекс к состоянию до начала rebase
git rebase --continue # продолжить конфликтный rebase (сработает только после разрешения конфликта и индексации такого разрешения)
Как отменить rebase
git reflog feature -2        # смотрим лог перемещений ветки, которой делали rebase (в этом примере — feature), видим последний коммит ПЕРЕД rebase, на него и нужно перенести указатель ветки
git reset --hard feature@{1} # переместить указатель ветки feature на один коммит назад, обновить рабочую директорию и индекс

Разное

git archive -o ./project.zip HEAD # создать архив с файловой структурой проекта по указанному пути (состояние репозитория, соответствующее указателю HEAD)

Примеры

Собираем коллекцию простых и сложных примеров работы.

Начало работы

Создание нового репозитория, первый коммит, привязка удалённого репозитория с gthub.com, отправка изменений в удалённый репозиторий.

# указана последовательность действий:
# создана директория проекта, мы в ней
git init                      # создаём репозиторий в этой директории
touch readme.md               # создаем файл readme.md
git add readme.md             # добавляем файл в индекс
git commit -m "Старт"         # создаем коммит
git remote add origin https://github.com:nicothin/test.git # добавляем предварительно созданный пустой удаленный репозиторий
git push -u origin master     # отправляем данные из локального репозитория в удаленный (в ветку master)

«Внесение изменений» в коммит

Только если коммит ещё не был отправлен в удалённые репозиторий.

# указана последовательность действий:
subl inc/header.html          # редактируем и сохраняем разметку «шапки»
git add inc/header.html       # индексируем измененный файл
git commit -m "Убрал телефон из шапки" # делаем коммит
# ВНИМАНИЕ: коммит пока не был отправлен в удалённый репозиторий
# сознаём, что нужно было еще что-то сделать в этом коммите.
subl inc/header.html          # вносим изменения
git add inc/header.html       # индексируем измененный файл (можно git add .)
git commit --amend -m "«Шапка»: выполнена задача №34" # заново делаем коммит

Работа с ветками

Есть master (публичная версия сайта), выполняем масштабную задачу (переверстать «шапку»), но по ходу работ возникает необходимость подправить критичный баг (неправильно указан контакт в «подвале»).

# указана последовательность действий:
git checkout -b new-page-header # создадим новую ветку для задачи изменения «шапки» и перейдём в неё
subl inc/header.html            # редактируем разметку «шапки»
git commit -a -m "Новая шапка: смена логотипа" # делаем коммит (работа еще не завершена)
# тут выясняется, что есть баг с контактом в «подвале»
git checkout master             # возвращаемся к ветке master
subl inc/footer.html            # устраняем баг и сохраняем разметку «подвала»
git commit -a -m "Исправление контакта в подвале" # делаем коммит
git push                        # отправляем коммит с быстрым критическим изменением в master в удалённом репозитории
git checkout new-page-header    # переключаемся обратно в ветку new-page-header для продолжения работ над «шапкой»
subl inc/header.html            # редактируем и сохраняем разметку «шапки»
git commit -a -m "Новая шапка: смена навигации" # делаем коммит (работа над «шапкой» завершена)
git checkout master             # переключаемся в ветку master
git merge new-page-header       # вливаем в master изменения из ветки new-page-header
git branch -d new-page-header   # удаляем ветку new_page_header

Работа с ветками, слияние и откат к состоянию до слияния

Была ветка fix, в которой исправляли баг. Исправили, влили fix в master. но тут выяснилось, что это исправление ломает какую-то функциональность, Нужно откатить master к состоянию без слияния (наличие бага менее критично, чем порча функциональности).

# находимся в ветке fix, баг уже «исправлен»
git checkout master            # переключаемся на master
git merge fix                  # вливаем изменения из fix в master
# видим проблему: часть функциональности сломалась
git checkout fix               # переключаемся на fix (пока мы в master, git не даст ее двигать)
git branch -f master ORIG_HEAD # передвигаем ветку master на коммит, указанный в ORIG_HEAD (тот, на который указывала master до вливания fix)

Работа с ветками, конфликт слияния

Есть ветка master (публичная версия сайта), в двух параллельных ветках (branch-1 и branch-2) было отредактировано одно и то же место одного и того же файла, первую ветку (branch-1) влили в master, попытка влить вторую вызывает конфликт.

# указана последовательность действий:
git checkout master           # переключаемся на ветку master
git checkout -b branch-1      # создаём ветку branch-1, основанную на ветке master
subl .                        # редактируем и сохраняем файлы
git commit -a -m "Правка 1"   # коммитим
git checkout master           # возвращаемся к ветке master
git checkout -b branch-2      # создаём ветку branch-2, основанную на ветке master
subl .                        # редактируем и сохраняем файлы
git commit -a -m "Правка 2"   # коммитим
git checkout master           # возвращаемся к ветке master
git merge branch-1            # вливаем изменения из ветки branch-1 в текущую ветку (master), удача (автослияние)
git merge branch-2            # вливаем изменения из ветки branch-2 в текущую ветку (master), КОНФЛИКТ автослияния
# Automatic merge failed; fix conflicts and then commit the result.
subl .                        # выбираем в конфликтных файлах те участки, которые нужно оставить, сохраняем
git commit -a -m "Устранение конфликта" # коммитим результат устранения конфликта

Синхронизация репозитория-форка с мастер-репозиторием

Есть некий репозиторий на github.com, он него нами был сделан форк, добавлены какие-то изменения. Оригинальный (мастер-)репозиторий был как-то обновлён. Задача: стянуть с мастер-репозитория изменения (которые там внесены уже после того, как мы его форкнули).

# указана последовательность действий:
git remote add upstream https://github.com:address.git # добавляем удаленный репозиторий: сокр. имя — upstream, URL мастер-репозитория
git fetch upstream            # стягиваем все ветки мастер-репозитория, но пока не сливаем со своими
git checkout master           # переключаемся на ветку master своего репозитория
git merge upstream/master     # вливаем стянутую ветку master удалённого репозитория upstream в свою ветку master

Ошибка в работе: закоммитили в мастер, но поняли, что нужно было коммитить в новую ветку

ВАЖНО: это сработает только если коммит еще не отправлен в удалённый репозиторий.

# указана последовательность действий:
# сделали изменения, проиндексировали их, закоммитили в master, но ЕЩЁ НЕ ОТПРАВИЛИ (не делали git push)
git checkout -b new-branch    # создаём новую вертку из master
git checkout master           # переключаемся на master
git reset HEAD~ --hard        # сдвигаем указатель (ветку) master на 1 коммит назад
git checkout new-branch       # переключаемся обратно на новую ветку для продолжения работы

Нужно вернуть содержимое файла к состоянию, бывшему в каком-либо коммите (известен хеш коммита)

# указана последовательность действий:
git checkout f26ed88 -- index.html # восстановить в рабочей директории состояние указанного файла на момент указанного коммита, добавить это изменение в индекс
git commit -am "Navigation fixs"   # сделать коммит

При любом действии с github (или другим удалённым сервисом) запрашивается логин и пароль

Речь именно о запросе пары логин + пароль, а не ключевой фразы. Происходит это потому, что git по умолчанию не сохранит пароль для доступа к репозиторию по HTTPS.

Простое решение: указать git кешировать ваш пароль.

.gitattributes

* text=auto

*.html diff=html
*.css  diff=css
*.scss diff=css

Git Commit — SYSOUT

Эта статья – шпаргалка по команде commit и сопутствующим ей командам: add, rm, reset. Здесь рассказывается, как отправить файлы в локальный репозиторий (commit), как подготовить их к отправке (add), как отменить последний снимок (с помощью команды reset) и как удалить отдельные файлы из индекса или даже из снимка.

Команда git add

Команда commit отправляет файлы в локальный репозиторий.

Однако перед выполнением команды commit надо подготовить файлы – составить список тех из них, которые будут отправлены в репозиторий. Команда git add позволяет это сделать – добавляет файлы и папки в индекс (область staging area). В GIT есть понятие staged files – это файлы, которые попадут в следующий снимок при выполнении команды commit.

Дело в том, что в параметрах commit не указывается, какие файлы включать в снимок. Это делается заранее в команде add, а в команде commit пишется просто комментарий и в репозиторий отправляются все подготовленные файлы из индекса (staging area).

Можно добавлять в индекс как файлы, так и папки. Например, эта команда подготовит для будущего снимка папку <имя_папки1> и файл <имя_файла1>:

git add <имя_файла1> <имя_папки1>

При этом все остальные файлы, даже если они отслеживаются в репозитории (tracked files) и были отредактированы (edited files), в следующий снимок не попадут.

Есть удобные вариации команды add:

git add -A добавляет все файлы (вновь созданные, измененные и удаленные)
git add . добавляет вновь созданные и измененные файлы, но не удаленные
git add -u добавляет измененные и удаленные, но не вновь созданные

Нетрудно заметить, что команда:

git add -A

эквивалентна двум поочередно выполненным командам:

git add .
git add -u

Удаление файлов из репозитория и с диска

Возможно, вам покажется странной фраза “добавляет удаленные файлы”. На самом деле это нормально: чтобы удалить файл из локального репозитория, недостаточно просто удалить его с диска. Надо после этого еще выполнить определенную команду git.

Если речь идет об отдельном файле, то команда:

git rm <имя_файла>

добавляет файл <имя_файла> в индекс как удаленный. При этом файл удаляется и с диска, если еще не был удален оттуда.

А команда:

git add -u

позволяет выполнить git rm для всех удаленных с диска файлов одновременно, то есть отправить их в индекс.

Удаление файлов только из репозитория

Бывает надо удалить файлы из репозитория, но не удалять с диска. Например, мы отправили в репозиторий логи, которым там не место.

А на диске они должны оставаться. Чтобы добавить этот лог в индекс как удаленный, но оставить его при этом на диске, выполним команду:

git rm --cached mylogfile.log

То же самое для папки делается так:

git rm --cached -r mydirectory

Что войдет в следующий снимок

Чтобы посмотреть, что же вы итоге подготовили для снимка, выполните команду:

$ git diff --name-only --cached

Благодаря параметру –name-only выведутся только названия файлов.

Команда git commit

А дальше просто – отправьте в локальный репозиторий все находящиеся в индексе файлы, комментарий обязателен:

$ git commit -m "комментарий"

Эта команда создает новый snapshot – снимок репозитория. К этому снимку можно будет вернуться в будущем. Ваши данные и комментарий будут также доступны при просмотре истории.

add и commit одной строкой

Бывает удобным отправлять файлы в репозиторий побыстрее, не выполняя по очереди add и commit. Можно выполнить эти команды и вместе:

git commit -a -m "комментарий"

Вышеприведенная команда – это то же самое, что выполненные по очереди команды:

git add .
git commit -m "комментарий"

Кратко это звучит как “добавь в индекс все измененные файлы и сделай снимок с указанным комментарием”.

Обратите внимание, что удаленные файлы затронуты не будут.

Но можно создать в конфигурации любую команду из комбинации add и commit (правда, это редко используется):

git config --global alias.add-commit '!git add -A && git commit'

Мы создали команду add-commit. И с помощью нее можем выполнять действия:

git add-commit -m 'комментарий'

Как отменить последний commit

Чтобы отменить последний локальный commit, выполните команду:

git reset HEAD~1

HEAD~1 указывает на предыдущую ревизию, так что команда вернет репозиторий к предыдущему состоянию.

Как отменить git add

Чтобы удалить все файлы из staging area, выполните команду:

git reset

Чтобы удалить конкретный файл, выполните команду:

git reset <имя_файла>

Как удалить некоторые файлы из снимка

Специальной команды тут нет. Для этого надо отменить последнюю команду commit. Эта команда сдвигает указатель на предыдущее состояние:

git reset HEAD~1

В индексе останутся файлы. Надо удалить из индекса нежелательный файл:

git reset path/to/unwanted_file

Подробнее о команде reset читайте здесь.

И затем снова отправить файлы в репозиторий. Следующая команда позволит задействовать при отправке метаданные предыдущего коммита, в том числе предыдущий комментарий:

git commit -c ORIG_HEAD

ORIG_HEAD – ссылка на предыдущий снимок.

Как исправить комментарий снимка

Допустим, мы уже отправили изменения в локальный репозиторий, но надо исправить комментарий, так как в него закралась ошибка. Делаем так:

git commit --amend -m 'новый комментарий'

 

git amend | Atlassian Git Tutorial

Введение

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

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

В Git существует несколько механизмов хранения истории и сохранения изменений. Вот эти механизмы: commit --amend, git rebase и git reflog. Это мощные инструменты для настройки рабочего процесса. По окончании работы с этим обучающим материалом вы будете знать команды, позволяющие реструктурировать коммиты Git, и сможете избежать проблем, с которыми приходится сталкиваться при перезаписи истории.

Изменение последнего коммита: git commit --amend

Команда git commit --amend — это удобный способ изменить последний коммит. Она позволяет объединить проиндексированные изменения с предыдущим коммитом без создания нового коммита. Ее также можно использовать для простого редактирования комментария к предыдущему коммиту без изменения состояния кода в нем. Но такое изменение приводит не только к редактированию последнего коммита, но и к его полной замене. Это означает, что измененный коммит станет новой сущностью с отдельной ссылкой. Для Git он будет выглядеть как новый коммит — на схеме ниже он отмечен звездочкой (*). Существует несколько распространенных сценариев использования команды git commit --amend. В следующих разделах мы приведем такие примеры.

Изменение комментария к последнему коммиту Git

 git commit --amend 

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

В процессе разработки регулярно случаются преждевременные коммиты. Очень просто забыть проиндексировать файл или использовать неправильный формат комментария к коммиту. Флаг --amend позволяет без труда исправить эти небольшие ошибки.

 git commit --amend -m "обновленный комментарий к коммиту" 

Добавление опции -m позволяет передать новый комментарий из командной строки, не открывая текстовый редактор.

Изменение файлов после коммита

В следующем примере показан распространенный сценарий разработки с использованием Git. Допустим, вы отредактировали несколько файлов и хотите сделать коммит за одну операцию. Но потом выясняется, что вы забыли добавить один из файлов в самом начале. Чтобы исправить эту ошибку, достаточно проиндексировать другой файл и выполнить коммит с флагом --amend:

 # Отредактируйте файлы hello.py и main.py git add hello.py git commit # Вспомните, что вы забыли добавить изменения из файла main.py git add main.py git commit --amend --no-edit 

Флаг --no-edit позволяет внести изменения в коммит без изменения комментария к нему. Итоговый коммит заменит неполный коммит. При этом все будет выглядеть так, словно изменения в файлах hello.py и main.py были сделаны за один коммит.

Не используйте amend для публичных коммитов

Измененные коммиты по сути представляют собой новые коммиты. При этом предыдущий коммит не остается в текущей ветке. Последствия этой операции аналогичны сбросу (reset) публичного состояния кода. Не изменяйте коммит, после которого уже начали работу другие разработчики. Эта ситуация только запутает разработчиков, и разрешить ее будет непросто.

Обзор

Если коротко, команда git commit --amend позволяет добавить новые проиндексированные изменения в последний коммит. С помощью коммита --amend можно добавлять изменения в индекс Git или удалять таковые из него. Если никаких изменений не проиндексировано, при использовании флага --amend вам все равно будет предложено изменить комментарий к последнему коммиту. Будьте осторожны при использовании флага --amend с коммитами, доступными другим членам команды. Изменение коммита, доступного другому пользователю, может привести к путанице и длительным устранениям конфликтов при слиянии.

Изменение старых или нескольких коммитов

Для изменения старых или нескольких коммитов используйте команду git rebase, чтобы объединить несколько коммитов в новый базовый коммит. В стандартном режиме команда git rebase позволяет в буквальном смысле перезаписать историю: она автоматически применяет коммиты в текущей рабочей ветке к указателю head переданной ветки. Поскольку новые коммиты заменяют старые, команду git rebase запрещено применять к коммитам, которые стали доступны публично, иначе история проекта исчезнет.

В таких или подобных случаях, когда важно сохранить чистую историю проекта, добавление опции -i к команде git rebase позволяет выполнить интерактивную операцию rebase interactive. Это дает возможность изменить отдельные коммиты в процессе вместо перемещения всех коммитов. Подробную информацию об интерактивной операции rebase и дополнительных командах перебазирования см. на странице git rebase.

Изменение файлов после коммита

Во время операции rebase команда редактирования (edit, илиe) остановит процесс на указанном коммите и позволит вам внести дополнительные изменения с помощью команды git commit --amend. Git прервет работу и выведет следующее сообщение:

 Stopped at 5d025d1... formatting Теперь можно исправить коммит с помощью git commit --amend Внеся изменения, выполните команду git rebase --continue 
Несколько комментариев

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

  • Опция reword, или r, остановит операцию rebase и позволит переписать отдельный комментарий к коммиту.
  • Опция squash, или s, приостановит операцию rebase для любых коммитов, отмеченных символом s, и вам будет предложено ввести один общий комментарий вместо нескольких отдельных. Подробнее об этом можно узнать в разделе о склеивании коммитов ниже.
  • Опция fixup, или f, позволяет объединить комментарии, как и squash. При этом, в отличие от squash, опция fixup не прерывает операцию rebase с открытием редактора для объединения комментариев к коммитам. В коммитах, отмеченных символом f, комментарии будут сброшены и заменены комментарием предыдущего коммита.
Склеивайте коммиты для поддержания чистой истории

Команда склеивания (s) позволяет в полной мере понять смысл rebase. Склеивание дает возможность указать коммиты, которые нужно объединить в предыдущие коммиты. Таким образом создается «чистая история». Во время перебазирования Git будет исполнять указанную команду rebase для каждого коммита. В случае склеенных коммитов Git откроет выбранный текстовый редактор и предложит объединить комментарии к указанным коммитам. Этот процесс можно представить следующим образом:

Обратите внимание, что идентификаторы коммитов, измененных с помощью команды rebase, отличаются от идентификаторов каждого из начальных коммитов. Коммиты с маркером pick получат новый идентификатор, если предыдущие коммиты были переписаны.

Современные решения для хостинга Git (например, Bitbucket) предоставляют возможности «автосклеивания» при слиянии. Это позволяет автоматически выполнять rebase и склеивать коммиты ветки при использовании интерфейса решений для хостинга. Дополнительную информацию см. в разделе «Склеивание коммитов при слиянии ветки Git в Bitbucket».

Обзор

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

Страховка: git reflog

Журналы ссылок (reflog) — это механизм, который используется в Git для регистрации обновлений, применяемых к концам веток и другим ссылкам на коммиты. Reflog позволяет вернуться к коммитам, даже если на них нет ссылок из какой-либо ветки или метки. После перезаписи истории reflog содержит информацию о прежнем состоянии веток и позволяет при необходимости вернуться к этому состоянию. Каждый раз при обновлении конца ветки любым способом (переключение веток, загрузка новых изменений, перезапись истории или просто добавление новых коммитов) в reflog добавляется новая запись. В этом разделе мы рассмотрим команду git reflog и некоторые стандартные примеры ее использования.

Использование

 git reflog 

Отображает reflog локального репозитория.

 git reflog --relative-date 

Отображает reflog с относительными датами (например, 2 недели назад).

Пример

Чтобы понять команду git reflog, давайте разберем пример.

 0a2e358 HEAD@{0}: reset: moving to HEAD~2 0254ea7 HEAD@{1}: checkout: moving from 2.2 to master c10f740 HEAD@{2}: checkout: moving from master to 2.2 

В вышеприведенной команде reflog показан переход из ветки master в ветку 2.2 и обратно. Отсюда можно выполнить жесткий сброс к старому коммиту. Последнее действие указано в верхней строчке с пометкой HEAD@{0}.

Если вы случайно переместитесь назад, reflog будет содержать главный коммит, указывающий на (0254ea7) до случайного удаления вами 2 коммитов.

git reset --hard 0254ea7

При использовании команды git reset можно вернуть главную ветку к более раннему коммиту. Это страховка на случай непреднамеренного изменения истории.

Важно отметить, что reflog обеспечивает страховку только на тот случай, когда изменения попали в коммит в локальном репозитории и в нем отслеживаются только перемещения концов веток репозитория. Кроме того, записи reflog имеют определенный срок хранения. По умолчанию этот срок составляет 90 дней.

Дополнительную информацию см. на странице git reflog.

Резюме

В этой статье мы обсудили несколько способов изменения истории и отмены изменений в Git. Мы вкратце рассмотрели процесс git rebase. Вот основные заключения.

  • Существует несколько способов переписать историю в Git.
  • Используйте команду git commit --amend для изменения своего последнего сообщения в журнале.
  • Используйте команду git commit --amend для внесения изменений в самый последний коммит.
  • Используйте команду git rebase для объединения коммитов и изменения истории ветки.
  • Команда git rebase -i обеспечивает более точный контроль над изменениями истории, чем обычный вариант git rebase.

Узнайте больше об описанных командах на соответствующих страницах:

Git happens! 6 типичных ошибок Git и как их исправить / Блог компании Флант / Хабр

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

Все мы делаем ошибки, особенно при работе с такими сложными системами, как Git. Но помните: Git happens!

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

1. Упс… Я ошибся в сообщении к последнему коммиту

После нескольких часов кодинга легко допустить ошибку в сообщении коммита. К счастью, это легко исправить:

git commit --amend

С этой командой откроется текстовый редактор и позволит внести изменения в сообщение к последнему коммиту. И никто не узнает, что вы написали «addded» с тремя «d».

2. Упс… Я забыл добавить файл к последнему коммиту

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

Добавьте недостающий файл и выполните эту верную команду:

git add missed-file.txt
git commit --amend

Теперь вы можете либо откорректировать сообщение, либо просто сохранить его в прежнем виде (с добавленным файлом).

3. Упс… Я добавил файл, который не должен быть в этом репозитории

Но что, если у вас обратная ситуация? Что, если вы добавили файл, который не хотите коммитить? Обманчивый ENV-файл, директорию сборки или фото с котом, что было случайно сохранено в неправильном каталоге… Всё решаемо.

Если вы сделали только stage для файла и ещё не коммитнули его, всё делается через простой reset нужного файла (находящегося в stage):

git reset /assets/img/misty-and-pepper.jpg

Если же вы всё-таки коммитнули изменение, потребуется дополнительный предварительный шаг:

git reset --soft HEAD~1
git reset /assets/img/misty-and-pepper.jpg
rm /assets/img/misty-and-pepper.jpg
git commit

Коммит будет откачен, картинка удалена, а затем сделан новый коммит.

Прим. перев.: Как замечено в комментариях к оригинальной статье, эту проблему тоже можно решить с помощью уже упомянутого --amend. По всей видимости, данным пунктом автор хотел показать, какие ещё есть способы изменения истории коммитов для исправления ошибки.

4. Упс… Я коммитнул изменения в master

Итак, вы работаете над новой фичей и поспешили, забыв создать новую ветку для неё. Вы уже коммитнули кучу файлов и все эти коммиты оказались в master’е. К счастью, GitLab может предотвращать push’ы прямо в master. Поэтому мы можем откатить все нужные изменения в новую ветку следующими тремя командами:

Примечание: Убедитесь, что сначала коммитнули или stash‘нули свои изменения — иначе все они будут утеряны!

git branch future-brunch
git reset HEAD~ --hard
git checkout future-brunch

Будет создана новая ветка, в master’е — произведён откат до состояния, в котором он был до ваших изменений, а затем сделан checkout новой ветки со всеми вашими изменениями.

5. Упс… Я сделал ошибку в названии ветки

Самые внимательные могли заметить в предыдущем примере ошибку в названии ветки. Уже почти 15:00, а я всё ещё не обедал, поэтому мой голод назвал новую ветку (branch) как future-brunch. Вкуснотища!

Переименуем эту ветку аналогичным способом, что используется при переименовании файла с помощью команды mv, то есть поместив её в новое место с правильным названием:

git branch -m future-brunch feature-branch

Если вы уже push’нули эту ветку, понадобится пара дополнительных шагов. Мы удалим старую ветку из remote и push’нем новую:

git push origin --delete future-brunch
git push origin feature-branch

Прим. перев.: Удалить ветку из remote ещё можно с помощью:

git push origin :future-brunch

6. Oops… I did it again!

Последняя команда на тот случай, когда всё пошло не так. Когда вы накопировали и навставляли кучу решений со Stack Overflow, после чего в репозитории всё стало ещё хуже, чем было в начале. Все мы однажды сталкивались с подобным…

git reflog показывает список всех выполненных вами операций. Затем он позволяет использовать магические возможности Git’а по путешествию во времени, т.е. вернуться к любому моменту из прошлого. Должен отметить, что это ваша последняя надежда — не стоит прибегать к ней в простых случаях. Итак, чтобы получить список, выполните:

git reflog

Каждый наш шаг находится под чутким наблюдением Git’а. Запуск команды на проекте выше выдал следующее:

3ff8691 (HEAD -> feature-branch) HEAD@{0}: Branch: renamed refs/heads/future-brunch to refs/heads/feature-branch
3ff8691 (HEAD -> feature-branch) HEAD@{2}: checkout: moving from master to future-brunch
2b7e508 (master) HEAD@{3}: reset: moving to HEAD~
3ff8691 (HEAD -> feature-branch) HEAD@{4}: commit: Adds the client logo
2b7e508 (master) HEAD@{5}: reset: moving to HEAD~1
37a632d HEAD@{6}: commit: Adds the client logo to the project
2b7e508 (master) HEAD@{7}: reset: moving to HEAD
2b7e508 (master) HEAD@{8}: commit (amend): Added contributing info to the site
dfa27a2 HEAD@{9}: reset: moving to HEAD
dfa27a2 HEAD@{10}: commit (amend): Added contributing info to the site
700d0b5 HEAD@{11}: commit: Addded contributing info to the site
efba795 HEAD@{12}: commit (initial): Initial commit

Обратите внимание на самый левый столбец — это индекс. Если вы хотите вернуться к любому моменту в истории, выполните следующую команду, заменив {index} на соответствующее значение (например, dfa27a2):

git reset HEAD@{index}

Итак, теперь у вас есть шесть способов выбраться из самых частых Gitfalls (игра слов: pitfall переводится как «ловушка, ошибка» — прим. перев.).

Бонус от переводчика

Во-первых, ценное замечание ко всему написанному выше (кроме пункта 5). Нужно учитывать, что эти действия меняют историю коммитов, поэтому их следует проводить, только если изменения не были отправлены в remote (push’нуты). В противном случае старый плохой коммит уже будет на remote-ветке и придётся либо выполнять git pull (который сделает merge, и тогда попытка «почистить» историю приведёт к худшим последствиям), либо git push --force, что чревато потерей данных при работе с веткой нескольких человек…

Теперь — небольшие полезные дополнения из нашего опыта:

  • Если вы (случайно или нет) сменили ветку и вам нужно вернуться на предыдущую, самый быстрый способ — использовать git checkout -.
  • Если вы случайно добавили к коммиту файл, который не должен быть туда добавлен, но ещё не сделали коммит — используйте git reset HEAD path/to/file. Похожая ситуация описана в пункте 3, но в действительности она шире, т.к. относится к любым ненужным изменениям в коммите (не только к случаю лишнего файла).
  • Хорошей практикой, чтобы не закоммитить лишнего, является использование параметра -p при добавлении файла к коммиту (git add -p). Это позволяет сделать review каждого изменения, которое уйдёт в коммит. Но стоит помнить, что он не добавляет к коммиту untracked-файлы — их нужно добавлять без этого параметра.
  • Ряд хороших рекомендаций (в том числе и более сложных), можно найти в статье 2014 года «Git Tutorial: 10 Common Git Problems and How to Fix Them». В частности, обратите внимание на использование git revert и git rebase -i.

P.S. от переводчика

Читайте также в нашем блоге:

Удалить файлы из Git commit

Переполнение стека

  1. Около
  2. Продукты

  3. Для команд
  1. Переполнение стека
    Общественные вопросы и ответы

  2. Переполнение стека для команд
    Где разработчики и технологи делятся частными знаниями с коллегами

  3. Вакансии
    Программирование и связанные с ним технические возможности карьерного роста

  4. Талант
    Нанимайте технических специалистов и создавайте свой бренд работодателя

  5. Реклама
    Обратитесь к разработчикам и технологам со всего мира

  6. О компании

.

github — полностью удалить файл из всего репозитория git

Переполнение стека

  1. Около
  2. Продукты

  3. Для команд
  1. Переполнение стека
    Общественные вопросы и ответы

  2. Переполнение стека для команд
    Где разработчики и технологи делятся частными знаниями с коллегами

  3. Вакансии
    Программирование и связанные с ним технические возможности карьерного роста

  4. Талант
    Нанимайте технических специалистов и создавайте свой бренд работодателя

  5. Реклама
    Обратитесь к разработчикам и технологам со всего мира

  6. О компании

.

Как полностью удалить файл из репозитория Git

Введение

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

Для всех нас: НЕ ПАНИКА! Сделайте глубокий вдох, встаньте из-за стола, пройдитесь несколько минут. Готов? Ладно, приступим!

Цель состоит в том, чтобы полностью стереть файл из репозитория Git, чтобы скрыть все следы вашей ужасной ошибки.Вы хотите быть человеком, который передал ключи AWS в общедоступный репозиторий GitHub, только чтобы через 24 часа узнать, что на майнинг биткойнов было потрачено ~ 2000 долларов США?

Несколько методов

Просто git rm passwords.txt этого не сделает, так как файл будет присутствовать во всех предыдущих коммитах. В зависимости от того, где находится файл, вы можете использовать несколько методов. Здесь представлен обзор каждого сценария в порядке возрастания сложности.

Примечания:

  • Все эти методы предполагают, что вы знакомы с консольными командами.

  • Они написаны для Linux, но должны работать в OS X и даже в Windows, если вы используете Git Bash.

  • Если вы уже внесли изменения, все может усложниться.

  • Если вы разработчик-одиночка, дерзайте. Но если вы работаете в команде, сначала обсудите это с ними.

  • Если ваш код (с ненужным файлом) уже открыт (GitHub, BitBucket ,…) тогда вам может не повезти. Но продолжайте читать до конца.

Сценарий 1: файл находится в последней фиксации, а вы еще не отправили

1. Вы хотите сохранить файл локально

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

  git rm --cached $ FILE
эхо $ ФАЙЛ >> .gitignore
git добавить .gitignore
git commit --amend --no-edit
git reflog expire --expire = now --all && git gc --prune = now --aggressive
  

Команды git reflog expire и git gc вызывают сборку мусора, чтобы файл не зависал где-нибудь в вашем репозитории.

2. Вы не хотите хранить файл локально

Просто измените последний коммит.

  git rm $ ФАЙЛ
git commit --amend --no-edit
git reflog expire --expire = now --all && git gc --prune = now --aggressive
  

Сценарий 2: файл находится дальше в истории, и вы еще не нажали

Решение 1: BFG Repo-Cleaner

Загрузите ‘BFG Repo-Cleaner’ здесь. Этот инструмент утверждает, что работает в 10-720 раз быстрее, чем любой другой метод, но вы не можете указать подкаталог, он удалит все файлы с тем же именем в любом каталоге.

Обычно BFG Repo-Cleaner защищает ваш последний коммит, но если вы знаете, что делаете (и знаете, верно?), Вы даете ему опцию --no-blob-protection , что вроде как сказать , делай что хочу и не защищай меня от ошибок.

  java -jar bfg.jar --delete-files $ FILE --no-blob-protection.
rm $ FILE
git reflog expire --expire = now --all && git gc --prune = now --aggressive
  

Решение 2. Интерактивная переустановка

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

У этой команды есть подоболочка внутри $ (...) : она находит первую фиксацию, в которую был добавлен файл, даже с учетом переименований файла. Затем команда за пределами $ (...) запускает интерактивную перебазировку в родительском ( ~ ) этого коммита.

  git rebase --interactive \
    $ (git log --follow --find-renames = 40% --diff-filter = A --format =% H - $ FILE) ~
  

Отредактируйте файл git-rebase-todo : измените первую команду с выбора на редактирование.

  edit 7b0a4be987 Добавить новую таблицу тестов ширины
pick 38737174a7 Избегайте использования метода FontProgram # getBaseName, когда он не подходит, обновите документацию
pick 66f95dd41b Обобщить чтение байтов для преобразования формата woff

# Rebase d1613dff58..66f95dd41b на d1613dff58 (3 команды)
#
# Команды:
# p, pick = использовать фиксацию
# r, reword = использовать фиксацию, но отредактировать сообщение фиксации
# e, edit = использовать фиксацию, но не вносить поправки
# s, squash = использовать фиксацию, но сливается с предыдущей фиксацией
# f, fixup = как "squash", но удалить сообщение журнала этой фиксации
# x, exec = run команда (остальная часть строки) с использованием оболочки
# d, drop = удалить фиксацию
#
# Эти строки можно переупорядочить; они выполняются сверху вниз.#
# Если вы удалите здесь строчку, ЧТО COMMIT БУДЕТ УТЕРЯНЫ.
#
# Однако, если вы удалите все, перебазирование будет прервано.
#
# Обратите внимание, что пустые коммиты закомментированы
  

Затем сохраните и закройте редактор. Перебазирование откатит коммиты к фиксации, которая добавила нежелательный файл.

  git rm $ ФАЙЛ
эхо $ ФАЙЛ >> .gitignore
git добавить .gitignore
git commit --amend --no-edit
git rebase - продолжить
git reflog expire --expire = now --all && git gc --prune = now --aggressive
  

Решение 3. Git filter-branch

Это запускает сценарий, указанный в --tree-filter (f.пример: удалить определенный файл) при каждой фиксации. Это действительно МЕДЛЕННО! Это потому, что он должен проверять каждую фиксацию, запускать сценарий, выполнять фиксацию и переходить к следующей фиксации. Используйте это, когда есть теги или коммиты слияния между ошибочной фиксацией и HEAD, или когда нарушающий файл существует в нескольких ветвях. Другими словами, используйте в крайнем случае!

В этом скрипте я использую тот же трюк, чтобы найти первую фиксацию, которая добавляет ненужный файл, а затем я запускаю фильтр только на родительском этого коммита, вплоть до HEAD текущей ветки. git filer-branch всегда делает резервную копию и ставит перед исходной веткой префикс original . Команда git for-each-ref очищает эти резервные ветки, потому что мы действительно хотим избавиться от этого надоедливого файла. --tag-name-filter cat будет следить за тем, чтобы любые теги перемещались вместе с их коммитами.

  git фильтр-ветка -f \
    --prune-empty \
    --tag-name-filter cat \
    --tree-filter 'rm -f $ FILE' \
    $ (git log --follow --find-renames = 40% --diff-filter = A --format =% H - $ FILE) ~..ГОЛОВА
git for-each-ref --format = "% (refname)" refs / original / | xargs -n 1 git update-ref -d
git reflog expire --expire = now --all && git gc --prune = now --aggressive
  

Если вы хотите сделать это для всего репозитория (не стоит!):

  git фильтр-ветка -f \
    --prune-empty \
    --tag-name-filter cat \
    --tree-filter 'rm -f $ FILE' \
    -- --все
git for-each-ref --format = "% (refname)" refs / original / | xargs -n 1 git update-ref -d
git reflog expire --expire = now --all && git gc --prune = now --aggressive
  

Сценарий 3: вы уже отправили

  • Я не могу повторить это достаточно: сначала проконсультируйтесь с остальной частью вашей команды !!! Если вы этого не сделаете, вы сделаете их жизнь несчастной.

  • Во-вторых, сделайте резервную копию репозитория, прежде чем делать что-либо еще.

  • Затем: СОЗДАТЬ РЕЗЕРВНУЮ КОПИЮ !!!

  • Не знаю, упоминал ли я об этом уже, но действительно ли вы уверены, что сделали резервную копию?

  • Используйте один из описанных выше методов для удаления файла.

  • Принудительно нажмите, но знайте, что делаете, и помните о последствиях, потому что нет возможности вернуться, если у вас нет резервной копии. --force-with-lease должно быть здесь по умолчанию, потому что сначала проверяется, что вы не перезаписываете работу других людей. См. Также блог Atlassian для отличного объяснения.

      git push --force-with-lease origin $ BRANCH
      

Сценарий 4: коммиты уже находятся на GitHub

В этом случае существует риск того, что кто-то все еще может получить доступ к нежелательному файлу даже после принудительного нажатия.

Это можно сделать двумя способами:

  • , если они сделали форк или клон репозитория: принудительное нажатие обновит только наш репозиторий, оно не обновит форки / клоны.

  • , если они знают точный хэш коммита, добавившего файл (возможно, они его записали или веб-страница все еще находится в кеше браузера), по URL-адресу: https://github.com/$USER/ $ REPO / совершить / $ COMMIT

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

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

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

.

Как мне удалить большой файл из моей истории коммитов?

Если вы зафиксировали в своем репозитории большой файл, который занимает большой объем дискового пространства, простое удаление его в фиксации на самом деле не поможет.

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

Git’s filter-branch на помощь

Допустим, в предыдущем коммите вы случайно добавили 15-мегабайтную фотографию своего генерального директора по имени ceo.jpg . Чтобы полностью удалить файл из репозитория, вам необходимо выполнить следующую команду в каталоге вашего проекта:

  git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch путь / к / ceo.jpg' \
  --prune-empty --tag-name-filter cat - --all
  

Если файл был успешно удален, вы должны увидеть следующий результат:

  Rewrite ee94db7633e1bf370512d95e5ab57b851ad6c8cf (5/5)
Ссылка refs / Heads / master была переписана
  

Обновите .gitignore файл

На этом этапе рекомендуется обновить файл .gitignore , чтобы предотвратить случайное повторное принятие этого файла в будущем.

Примечание: Мы написали руководство для начинающих по файлам .gitignore .

Принудительная отправка на ваши пульты

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

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

Когда будете готовы, запустите эту команду:

  git push origin --force --all
  

Примечание: Пространство не обязательно будет освобождено на хосте немедленно. Вам нужно будет дождаться запуска сборки мусора, прежде чем размер будет пересчитан.

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *