Возврат определенных коммитов из git

У меня есть дерево git с большим количеством коммитов и большим количеством файлов. Теперь я хочу вернуть определенные коммиты, которые касаются только файла. Объяснить:

> git init
Initialized empty Git repository in /home/psankar/specific/.git/
> echo "File a" > a
> git add a ; git commit -m "File a"
[master (root-commit) 5267c21] File a
 1 file changed, 1 insertion(+)
 create mode 100644 a
> echo "File b" > b
> git add b; git commit -m "File b"
[master 7b560ae] File b
 1 file changed, 1 insertion(+)
 create mode 100644 b
> echo "File c" > c
> git add c; git commit -m "File c"
[master fd6c132] File c
 1 file changed, 1 insertion(+)
 create mode 100644 c
> echo "b and c modified" > b ; cp b c
> git commit -a -m "b and c modified"
[master 1d8b062] b and c modified
 2 files changed, 2 insertions(+), 2 deletions(-)
> echo "a modified" > a
> git commit -a -m "a modified"
[master 5b7e0cd] a modified
 1 file changed, 1 insertion(+), 1 deletion(-)
> echo "c modified" > c
> git commit -a -m "c modified"
[master b49eb8e] c modified
 1 file changed, 1 insertion(+), 1 deletion(-)
> git log --pretty=oneline c
> git log --pretty=oneline c | cat
b49eb8e03af331bddf90342af7d076f831282bc9 c modified
1d8b062748f23d5b75a77f120930af6610b8ff98 b and c modified
fd6c13282ae887598d39bcd894c050878c53ccf1 File c

теперь я хочу вернуть только два коммита b49eb8 и 1d8b06 без возврата изменений к a. IOW возвращает только коммиты в файле (без возврата других промежуточных коммитов (которые могут быть тысячами) в разных файлах) как это возможно ?

2 ответов


можно использовать git revert С . В вашем примере:

$ git revert --no-commit b49eb8e 1d8b062
# Files that were modified in those 2 commits will be changed in your working directory
# If any of those 2 commits had changed 'a' then you could discard the revert for it:
$ git checkout a
$ git commit -a -m "Revert commits b49eb8e and 1d8b062"

если вы не предоставите сообщение фиксации, подготовленное сообщение будет доступно при запуске редактора сообщений фиксации.

если вы ommit --no-commit опция тогда изменения в коммит, которые вы укажете, будут отменены. Это достигается путем применения обратного изменения указанных коммитов и фиксации этого. Это приводит к новой фиксации, как оригинальной, так и откатить коммит в истории вашего репозитория.


здесь есть два случая:

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

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

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

git rebase -i 23def8231

или если вы начали с филиала origin/dev_branch и делал работу, которая включает в себя биты для удаления вашего бранч крикнул dev_branch, вы могли бы сделать

git rebase -i origin/dev_branch

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

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

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

важные вещи, чтобы помнить:

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

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