git checkout после добавления git? - PullRequest
0 голосов
/ 30 мая 2019

Я хотел знать, есть ли способ вернуться к предыдущему изменению в файле на git. Если я создаю файл .txt, я редактирую его, но я не "git add", могу ли я запустить "git checkout - file.txt" и вернуться назад, но есть ли способ сделать это после выполнения "git add"?

Ответы [ 2 ]

2 голосов
/ 30 мая 2019

Я хотел знать, есть ли способ вернуться к предыдущему изменению файла в git.Если я создаю файл .txt, я редактирую его, но я не "git add", могу ли я запустить "git checkout - file.txt" и вернуться назад, но есть ли способ сделать это после выполнения "git add"?

При условии, что файл в Git , ответ - да.

Здесь важно понимать, что существует не один, а два изменяемые копии некоторых уже зафиксированных файлов, плюс много копий, которые не могут быть изменены .Копии только для чтения находятся в каждом коммите, потому что каждый коммит, который вы делаете, сохраняет полный снимок каждого файла. 1 Но он делает этот снимок не из копии , которую вы видите иработать с.Вместо этого он делает снимок из второй модифицируемой копии, которую Git хранит в том, что Git иногда называет index , а иногда - область подготовки .

Имена index и область подготовки относятся к одному и тому же.Его также иногда называют кеш . Гитлоссарий определяет кеш как "устаревший для индекса".Хороший способ представить индекс - это следующий предложенный коммит .Когда вы извлекаете какой-либо существующий коммит, Git заполняет оба индекса и рабочего дерева из этого существующего коммита.Когда вы запускаете git add <em>file</em>, Git копирует текущую версию file в индекс, заменяя копию, которая была в индексе.То есть git add просто обновляет предложенный новый коммит.

(Если бы Git делал коммиты прямо из рабочего дерева, вам бы вообще не понадобился индекс. Но Git не делает коммиты из работы-дерево, и индекс играет расширенную роль во время конфликтующего слияния, поэтому вы как бы застряли в изучении индекса.)

Обычно вы используете git checkout <em>branchname</em> для переключения на ветку, но вытакже можно написать git checkout [--] <em>filename</em> или git checkout <em>branchname</em> [--] <em>filename</em>. 2 Они оба отличаются от git checkout <em>branchname</em>:

  • git checkout <em>branchname</em> означает переключение ветвей .
  • git checkout <em>branchname</em> [--] <em>filename</em> означает получить указанный файл из коммита в конце указанной ветви . 3
  • git checkout [--] <em>filename</em> означает получить указанный файл из области индекса / размещения .

Мне нравится думать об этом так: когда вы работаете над созданием нового коммита, существует три активные копии файла.Один из них - фиксированный в вашем текущем (HEAD или @) коммите, один - изменяемая копия в вашем следующем предложенном коммите в индексе, а третий - обычный файл, который вы можете просматривать и работать с ним.При использовании git checkout -- file.txt в рабочее дерево, где вы можете с ним работать, копируется middle - индексная копия, которую вы уже перезаписали ранее git add.Следовательно, вы хотите git checkout HEAD -- file.txt: он получает фиксированную копию только для чтения.На этом этапе он попадает в индексы и в вашем рабочем дереве, поэтому обе изменяемые копии были перезаписаны этой одной командой. 4 Предлагаемый новый коммит имеетстарая версия file.txt вне текущего коммита, а ваше рабочее дерево имеет старую версию file.txt вне текущего коммита.Все три копии - HEAD, индекс и рабочее дерево - снова совпадают.


1 Это верно, хотя git log -p или git show показывает вам Различия между родителем коммита и коммитом.Это потому, что способ, которым git log -p или git show находит различия, заключается в том, что он извлекает как копию родительского коммита, так и копию коммита из файла, а затем сравнивает их, чтобы увидеть, что отличается.

Beпотому что зафиксированные копии являются только для чтения, каждый коммит, который повторно использует старую версию файла, не создает новую копию, он просто ссылается на существующую, уже замороженную копию. Таким образом, тот факт, что, скажем, README.md находится в тысяче коммитов со всеми одинаковыми README.md копиями, на самом деле означает, что есть одна копия, общая для тысячи коммитов.

2 Квадратные скобки в [--] указывают, что -- является необязательным. Полезно использовать его, когда вы имеете в виду , следующая часть - это имя файла . Предположим, вы создаете файл с именем master. Позже вы запускаете:

git checkout master

Вы имели в виду: Получите мне файл с именем master, или вы имели в виду: * Переключиться на ветку master `? Если вы введете:

git checkout -- master

Git знает, что вы имели в виду Получите мне файл с именем master. Все, что следует после --, считается именем файла. Если вы наберете это без --, Git думает, что вы имеете в виду переключиться на ветку master.

3 Здесь вы можете указать хеш-идентификатор коммита или любое другое имя или строку, которые разрешают коммит.

4 Будь таким, какой есть, есть еще один способ сделать все это. На самом деле есть много способов, но есть еще один основной способ: вы можете использовать git reset [--] <em>filename</em> для копирования из HEAD в индекс, а затем git checkout [--] <em>filename</em> для копирования из индекса в рабочее дерево. Но git checkout <em>commit-ish</em> -- <em>filename</em> короче и быстрее.

1 голос
/ 30 мая 2019

Этого трудно найти, так что вот оно. Если у вас есть незафиксированное изменение (только в вашей рабочей копии), которое вы хотите вернуть (в терминах SVN) к копии в вашем последнем коммите, сделайте следующее:

git checkout filename

Это извлечет файл из HEAD, перезаписав ваши изменения. Эта команда также используется для извлечения веток, и вы можете получить файл с тем же именем, что и ветка. Еще не все потеряно, вам просто нужно будет набрать:

git checkout -- filename

Вы также можете сделать это с файлами из других веток и тому подобным. У человека git-checkout есть детали.

Остальная часть Интернета скажет вам использовать git reset --hard, но при этом будут сброшены все незафиксированные изменения, внесенные вами в рабочую копию. Введите это с осторожностью.

из https://www.norbauer.com/rails-consulting/notes/git-revert-reset-a-single-file

...