Как изменить указанный коммит?

2233

Я обычно представляю список коммитов на рассмотрение. Если у меня есть следующие коммиты:

  1. HEAD
  2. Commit3
  3. Commit2
  4. Commit1

... Я знаю, что могу изменить коммит с головой git commit --amend. Но как я могу изменить Commit1, учитывая, что это не HEADкоммит?

Сэм Ляо
источник
31
Смотрите альтернативный ответ здесь: stackoverflow.com/a/18150592/520567 Ваш принятый ответ действительно является точным ответом на ваш вопрос, но если у вас есть готовый новый коммит, прежде чем вы решите использовать редактирование, тогда этот ответ будет более простым. Он также может работать с несколькими коммитами, которые вы хотите объединить / сквош вместе со старыми.
Акостадинов
6
Также вы можете просто посмотреть разделение коммита в Git Tools - Переписывание истории для получения дополнительной информации.
13

Ответы:

2957

Вы можете использовать git rebase . Например, если вы хотите изменить коммит bbc643cd, запустите

$ git rebase --interactive 'bbc643cd^'

Пожалуйста, обратите внимание на знак вставки ^в конце команды, потому что на самом деле вам нужно перебазировать обратно в коммит, прежде чем тот, который вы хотите изменить .

В редакторе по умолчанию измените pickна editв строке упоминание 'bbc643cd'.

Сохраните файл и выйдите: git будет интерпретировать и автоматически выполнять команды в файле. Вы окажетесь в предыдущей ситуации, в которой вы только что создали commit bbc643cd.

На данный момент bbc643cdэто ваш последний коммит, и вы можете легко изменить его : внести изменения, а затем зафиксировать их с помощью команды:

$ git commit --all --amend --no-edit

После этого введите:

$ git rebase --continue

вернуться к предыдущему коммиту HEAD.

ВНИМАНИЕ : обратите внимание, что это изменит SHA-1 этого коммита, а также всех дочерних элементов - другими словами, это переписывает историю с этого момента. Делая это , вы можете сломать репо, если нажмете командуgit push --force

ZelluX
источник
125
Еще один интересный вариант в этом потоке: после того, как вы перешли к коммиту, который хотите изменить, вместо того, чтобы изменять файлы и помещать их поверх коммита сверху (того, который вы редактируете), вы можете разделить этот коммит на два разных коммита. (или даже больше). В этом случае вернитесь к коммиту для редактирования и выполните «git reset HEAD ^». это поместит измененные файлы этого коммита на сцену. Теперь выберите и зафиксируйте любые файлы по вашему желанию. Этот поток довольно хорошо объяснен на странице руководства git-rebase. Смотрите раздел "Разделение коммитов". bit.ly/d50w1M
Диего Пино
200
В Git 1.6.6 и новее вы можете использовать rewordдействие git rebase -iвместо edit(оно автоматически открывает редактор и выполняет остальные шаги перебазирования; это исключает использование git commit --ammendи git rebase --continueкогда вам нужно только изменить сообщение фиксации, а не содержимое ).
Крис Джонсен
108
Стоит отметить, что вам может потребоваться запустить git stashдо git rebaseи git stash popпосле, если у вас есть ожидающие изменения.
user123444555621
3
Существует ли команда shortucut для редактирования определенного коммита в интерактивной перебазировке, не открывая редактор, не находя коммит, помечая его как редактирование, а затем возвращаясь в командную строку?
sstur
15
Обратите внимание, что с более новым git было бы разумнее следовать подсказкам, а не слепо использовать git commit --all --amend --no-editздесь. Все, что я должен был сделать после этого, git rebase -i ...- это git commit --amendнормально git rebase --continue.
Эрик Чен,
453

Используйте удивительный интерактивный ребаз:

git rebase -i @~9   # Show the last 9 commits in a text editor

Найдите нужный коммит, измените pickна e( edit), сохраните и закройте файл. Git перемотает на этот коммит, что позволит вам:

  • использовать git commit --amendдля внесения изменений, или
  • используйте git reset @~для отмены последнего коммита, но не для изменений в файлах (т. е. перенесите вас в тот момент, когда вы редактировали файлы, но еще не зафиксировали).

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

Затем запустите git rebase --continue, и Git воспроизведет последующие изменения поверх вашего измененного коммита. Вас могут попросить исправить некоторые конфликты слияния.

Примечание: @является сокращением для HEADи ~является коммитом перед указанным коммитом.

Узнайте больше о переписывании истории в Git docs.


Не бойся перебазировать

ProTip ™: не бойтесь экспериментировать с «опасными» командами, которые переписывают историю * - Git по умолчанию не удаляет ваши коммиты в течение 90 дней; вы можете найти их в reflog:

$ git reset @~3   # go back 3 commits
$ git reflog
c4f708b HEAD@{0}: reset: moving to @~3
2c52489 HEAD@{1}: commit: more changes
4a5246d HEAD@{2}: commit: make important changes
e8571e4 HEAD@{3}: commit: make some changes
... earlier commits ...
$ git reset 2c52489
... and you're back where you started

* Остерегайтесь опций, как --hardи --forceхотя - они могут отказаться от данных.
* Кроме того, не переписывайте историю ни в каких ветвях, над которыми вы сотрудничаете.



Во многих системах git rebase -iоткроется Vim по умолчанию. Vim не работает, как большинство современных текстовых редакторов, поэтому взгляните на то, как сделать перебаз с помощью Vim . Если вы предпочитаете использовать другой редактор, измените его с помощью git config --global core.editor your-favorite-text-editor.

Zaz
источник
29
Середина вашего ответа - странное место для размещения того, что я могу описать только как рекламное объявление для VIM. Это не имеет отношения к вопросу и просто загромождает ваш ответ.
Содержание
21
@Intentss: Ах, я понимаю, почему это выглядело странно. Причиной этого было то, что Vim является текстовым редактором по умолчанию во многих системах, поэтому первый опыт интерактивного перебазирования многих людей - это экран, на котором при наборе текста курсор перемещается повсюду. Затем они переключают свой редактор на что-то другое, и их второй опыт интерактивного перебазирования вполне нормален, но заставляет их задуматься, почему он использует текстовый файл вместо графического интерфейса. Чтобы добиться потока с помощью перебазирования, вам нужно что-то вроде Vim или Emacs 'rebase-mode.
Заз
9
Ладно. Ввиду того, что многие считают эту часть неактуальной, я сократил ее до 3 строк, а также объяснил, как изменить редактор в случае необходимости.
Zaz
17
Потрясающие! Я не знал, что вы могли бы использовать @как сокращение для HEAD. Спасибо за публикацию этого.
Джеймс Ко
3
git reset @~именно то, что я хотел сделать после выбора коммита git rebase .... Ты мой герой)
18
79

Интерактивные перебазироваться с --autosquashто , что я часто использую , когда мне нужно FixUp предыдущих коммитов глубже в истории. Это существенно ускоряет процесс, который иллюстрирует ответ ZelluX, и особенно удобно, когда вам нужно отредактировать более одного коммита.

Из документации:

--autosquash

Когда сообщение журнала фиксации начинается с «squash!…» (Или «fixup!…»), И существует коммит, заголовок которого начинается с того же…, автоматически изменяйте список задач для rebase -i так, чтобы коммит пометка для сквоша наступает сразу после изменения коммита

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

$ git log --graph --oneline
* b42d293 Commit3
* e8adec4 Commit2
* faaf19f Commit1

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

$ git commit -m "fixup! Commit2"

в качестве альтернативы вы можете использовать commit-sha вместо сообщения фиксации, "fixup! e8adec4или даже просто префикс сообщения фиксации.

Затем инициируйте интерактивную перебазировку коммита до

$ git rebase e8adec4^ -i --autosquash

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

pick e8adec4 Commit2
fixup 54e1a99 fixup! Commit2
pick b42d293 Commit3

все, что вам нужно сделать, это сохранить и выйти

thrau
источник
21
Вы также можете использовать git commit --fixup=@~вместо git commit -m "fixup! Commit2". Это особенно полезно, когда ваши сообщения фиксации длиннее, и было бы неудобно печатать все это.
Заз
42

Запустить:

$ git rebase --interactive commit_hash^

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

Использование Vim изменить слова , pickчтобы rewordдля фиксаций вы хотите изменить, сохранить и выйти ( :wq). Затем git предложит вам каждый коммит, который вы пометили как reword, чтобы вы могли изменить сообщение коммита.

Каждое сообщение коммита вы должны сохранить и выйти ( :wq), чтобы перейти к следующему сообщению коммита

Если вы хотите выйти без применения изменений, нажмите :q!

РЕДАКТИРОВАТЬ : для навигации vimиспользуйте jдля перехода вверх, kвниз, hвлево и lвправо (все это в NORMALрежиме, нажмите ESCдля перехода в NORMALрежим). Чтобы редактировать текст, нажмите, iчтобы войти в INSERTрежим, в который вы вставляете текст. Нажмите, ESCчтобы вернуться в NORMALрежим :)

ОБНОВЛЕНИЕ : Вот отличная ссылка из списка GitHub Как отменить (почти) все, что с Git

betoharres
источник
4
Работал отлично для меня. Стоит упомянуть git push --force?
u01jmg3
Что git push --forceперезаписывает удаленные коммиты с вашими локальными коммитами. Это не относится к этой теме :)
betoharres
@BetuUuUu, конечно, если ваши коммиты передаются на удаленное устройство, и вы локально изменили сообщение о коммите, вы бы хотели принудительно выдвинуть сообщение на удаленное, не так ли?
Судип Бхандари
@SudipBhandari Это чувство, которое я получаю. Я не форсировал, и теперь у меня есть дополнительная ветвь, отражающая все коммиты назад тому, чье сообщение я изменил, что очень уродливо.
Ерф
2
@greenhouse, если вы измените и принудительно нажмете, то другие члены команды, скорее всего, столкнутся с конфликтами слияния. Так что вы должны быть очень осторожны с этим. Но если вы модифицируете что-то, что еще никто не получил, это должно быть хорошо (он этого не заметит). Поэтому я бы посчитал --force последней инстанцией и всегда консультировался с репо с другими участниками.
Томаш Качмарзик
18

Если по какой-то причине вам не нравятся интерактивные редакторы, вы можете использовать git rebase --onto.

Скажи, что хочешь изменить Commit1. Во-первых, ветвь из ранее Commit1 :

git checkout -b amending [commit before Commit1]

Во-вторых, возьмите Commit1с собой cherry-pick:

git cherry-pick Commit1

Теперь внесите изменения, создав Commit1':

git add ...
git commit --amend -m "new message for Commit1"

И, наконец, после того, как вы спрятали любые другие изменения, перенесите остальные ваши коммиты masterна верх вашего нового коммита:

git rebase --onto amending Commit1 master

Читайте: «перебазировать на ветку amendingвсе коммиты между Commit1(не включительно) и master(включительно)». То есть, Commit2 и Commit3, полностью исключая старый Commit1. Вы можете просто выбрать их, но так проще.

Не забудьте убирать свои ветви!

git branch -d amending
FeepingCreature
источник
4
Вы можете использовать, git checkout -b amending Commit1~1чтобы получить предыдущий коммит
Арин Тейлор
Первые два шага эквивалентны git checkout -b amending Commit1?
Хаошу
16

На основании документации

Поправка к сообщению старых или нескольких сообщений коммита

git rebase -i HEAD~3 

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

pick e499d89 Delete CNAME
pick 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.

Замените pick на reword перед каждым коммит-сообщением, которое вы хотите изменить. Допустим, вы изменили второй коммит в списке, ваш файл будет выглядеть следующим образом:

pick e499d89 Delete CNAME
reword 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.

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

Окончательно Force-push исправленных коммитов.

git push --force
просто я
источник
Я получаю следующую ошибку: ошибка: возникла проблема с редактором 'vi'. Пожалуйста, укажите сообщение, используя опцию -m или -F.
Эрик Мейнард
12

Полностью неинтерактивная команда (1)

Я просто думал, что поделюсь псевдонимом, который я использую для этого. Он основан на неинтерактивном интерактивном ребазе. Чтобы добавить его в свой git, выполните эту команду (объяснение приведено ниже):

git config --global alias.amend-to '!f() { SHA=`git rev-parse "$1"`; git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"; }; f'

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


(1) учитывая, что нет никаких конфликтов во время перебазирования, конечно

Применение

git amend-to <REV> # e.g.
git amend-to HEAD~1
git amend-to aaaa1111

Название amend-toкажется подходящим ИМХО. Сравните поток с --amend:

git add . && git commit --amend --no-edit
# vs
git add . && git amend-to <REV>

объяснение

  • git config --global alias.<NAME> '!<COMMAND>'- создает глобальный псевдоним git, <NAME>который будет выполнять не-git команду<COMMAND>
  • f() { <BODY> }; f - анонимная функция bash.
  • SHA=`git rev-parse "$1"`; - преобразует аргумент в git revision и присваивает результат переменной SHA
  • git commit --fixup "$SHA"Fixup-коммит для SHA. См git-commitдокументы
  • GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"
    • git rebase --interactive "$SHA^" часть была покрыта другими ответами.
    • --autosquashэто то, что используется в сочетании с git commit --fixup, см. git-rebaseдокументы для получения дополнительной информации
    • GIT_SEQUENCE_EDITOR=trueэто то, что делает все это неинтерактивным. Этот взлом я узнал из этого поста в блоге .
Dethariel
источник
1
Можно также amend-toобрабатывать неподготовленные файлы: git config --global alias.amend-to '!f() { SHA=git rev-parse "$ 1"; git stash -k && git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^" && git stash pop; }; f'
Dethariel
2
Одна из проблем этого метода заключается в том, что он может применять несвязанные исправления.
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
Разве смысл вопроса не в том, чтобы изменить сообщение о коммите? Потому что этот ответ не касается этого, или, по крайней мере, не напрямую.
Уиттен
@wytten вопрос не об изменении сообщения коммита, а об изменении коммита, который не является HEAD. Таким образом, ответом на ваш вопрос будет «нет, дело не в этом»
Dethariel
Я в замешательстве, так как мы можем изменить сообщение коммита?
ggb667
8

Автоматическое интерактивное редактирование ребазирования с последующим коммитом, готовым к повторному выполнению

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

Вот рабочий процесс:

  1. git commit-edit <commit-hash>
    

    Это приведет вас к коммиту, который вы хотите отредактировать.

  2. Фиксируйте и ставьте коммит так, как вам хотелось бы.

    (Вы можете использовать git stash saveлюбые файлы, которые вы не делаете)

  3. Повторите коммит --amend, например:

    git commit --amend
    
  4. Завершите перебазирование:

    git rebase --continue
    

Чтобы вышеперечисленное сработало, поместите приведенный ниже скрипт в исполняемый файл, который называется git-commit-editгде-то в вашем $PATH:

#!/bin/bash

set -euo pipefail

script_name=${0##*/}

warn () { printf '%s: %s\n' "$script_name" "$*" >&2; }
die () { warn "$@"; exit 1; }

[[ $# -ge 2 ]] && die "Expected single commit to edit. Defaults to HEAD~"

# Default to editing the parent of the most recent commit
# The most recent commit can be edited with `git commit --amend`
commit=$(git rev-parse --short "${1:-HEAD~}")
message=$(git log -1 --format='%h %s' "$commit")

if [[ $OSTYPE =~ ^darwin ]]; then
  sed_inplace=(sed -Ei "")
else
  sed_inplace=(sed -Ei)
fi

export GIT_SEQUENCE_EDITOR="${sed_inplace[*]} "' "s/^pick ('"$commit"' .*)/edit \\1/"'
git rebase --quiet --interactive --autostash --autosquash "$commit"~
git reset --quiet @~ "$(git rev-parse --show-toplevel)"  # Reset the cache of the toplevel directory to the previous commit
git commit --quiet --amend --no-edit --allow-empty  #  Commit an empty commit so that that cache diffs are un-reversed

echo
echo "Editing commit: $message" >&2
echo
Том Хейл
источник
7

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

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

Скажем, вы хотите изменить коммит, 0и вы в настоящее время наfeature-branch

some-commit---0---1---2---(feature-branch)HEAD

Оформить заказ на эту фиксацию и создать quick-branch. Вы также можете клонировать свою функциональную ветвь как точку восстановления (перед запуском).

?(git checkout -b feature-branch-backup)
git checkout 0
git checkout -b quick-branch

Теперь у вас будет что-то вроде этого:

0(quick-branch)HEAD---1---2---(feature-branch)

Сценические изменения, прятать все остальное.

git add ./example.txt
git stash

Зафиксируйте изменения и вернитесь к feature-branch

git commit --amend
git checkout feature-branch

Теперь у вас будет что-то вроде этого:

some-commit---0---1---2---(feature-branch)HEAD
           \
             ---0'(quick-branch)

Перебазировать feature-branchна quick-branch(разрешить любые конфликты по пути). Примените тайник и удалите quick-branch.

git rebase quick-branch
git stash pop
git branch -D quick-branch

И вы в конечном итоге:

some-commit---0'---1'---2'---HEAD(feature-branch)

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

Примечание: все хеши коммитов меняются, начиная с коммита, который мы изначально намеревались изменить.

Ольга
источник
6

Чтобы получить неинтерактивную команду, поместите скрипт с этим содержимым в ваш PATH:

#!/bin/sh
#
# git-fixup
# Use staged changes to modify a specified commit
set -e
cmt=$(git rev-parse $1)
git commit --fixup="$cmt"
GIT_EDITOR=true git rebase -i --autosquash "$cmt~1"

Используйте его, поставив свои изменения (с git add), а затем запустите git fixup <commit-to-modify>. Конечно, он все равно будет интерактивным, если у вас возникнут конфликты.

Пелле Нильссон
источник
1
Это хорошо работает. Я добавил некоторые дополнительные функции, чтобы делать частичные исправления грязного дерева для совершенствования набора коммитов. `dirtydiff = $ (git diff); if ["$ {dirtydiff}"! = ""]; затем эхо "Скрытое грязное дерево"> & 2; заначка; Fi;
Саймон Фельтман
6

git stash+ rebaseавтоматизация

Когда мне нужно много раз модифицировать старый коммит для обзоров Геррита, я делаю:

git-amend-old() (
  # Stash, apply to past commit, and rebase the current branch on to of the result.
  current_branch="$(git rev-parse --abbrev-ref HEAD)"
  apply_to="$1"
  git stash
  git checkout "$apply_to"
  git stash apply
  git add -u
  git commit --amend --no-edit
  new_sha="$(git log --format="%H" -n 1)"
  git checkout "$current_branch"
  git rebase --onto "$new_sha" "$apply_to"
)

GitHub вверх по течению .

Применение:

  • изменить исходный файл, нет необходимости, git addесли уже в репо
  • git-amend-old $old_sha

Мне это нравится, --autosquashпотому что это не раздавливает другие несвязанные исправления.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
источник
Очень хороший обходной путь, это должна быть опция по умолчанию, git amendчтобы применить изменения к конкретному коммиту с использованием текущего тайника, очень умно!
Кайохамамура
5

Я решил это,

1) путем создания нового коммита с изменениями, которые я хочу ..

r8gs4r commit 0

2) я знаю, какой коммит мне нужно слить с ним. который совершает 3.

Итак, git rebase -i HEAD~4# 4 представляет последние 4 коммита (здесь коммит 3 находится на 4-м месте)

3) в интерактивном ребазе недавний коммит будет расположен внизу это будет выглядеть одинаково,

pick q6ade6 commit 3
pick vr43de commit 2
pick ac123d commit 1
pick r8gs4r commit 0

4) здесь нам нужно изменить коммит, если вы хотите объединить с конкретным. это должно быть как,

parent
|_child

pick q6ade6 commit 3
f r8gs4r commit 0
pick vr43de commit 2
pick ac123d commit 1

после перестановки необходимо заменить p pickна f( исправление объединится без сообщения фиксации) или s( объединение сквоша с сообщением фиксации может измениться во время выполнения)

а затем сохранить свое дерево.

Теперь слияние сделано с существующим коммитом.

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

Мохидин бен Мухаммед
источник
Это хорошее решение, если вы не хотите делать live-модификацию во время интерактивной перебазировки.
Дунатотатос
4

Наилучшим вариантом является использование «Интерактивной команды rebase» .

Команда git rebaseневероятно мощная. Он позволяет редактировать сообщения о коммитах , комбинировать коммиты, изменять их порядок ... и т. Д.

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

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

Теперь, как использовать эту команду?

git rebase -i <base> 

-iстенд для "интерактивного" . Обратите внимание, что вы можете выполнить ребаз в неинтерактивном режиме. например:

#interactivly rebase the n commits from the current position, n is a given number(2,3 ...etc)
git rebase -i HEAD~n 

HEADуказывает ваше текущее местоположение (может быть также именем филиала или коммитом SHA). ~nОзначает «п beforeé, так HEAD~nбудет список„п“фиксаций до того, вы в данный момент.

git rebase имеет другую команду, как:

  • pили pickсохранить коммит как есть.
  • rили reword: сохранить содержимое фиксации, но изменить сообщение фиксации.
  • sили squash: объединить изменения этого коммита в предыдущий коммит (коммит над ним в списке).
  • ... так далее.

    Примечание: лучше сделать так, чтобы Git работал с вашим редактором кода, чтобы все было проще. Например, если вы используете визуальный код, вы можете добавить вот так git config --global core.editor "code --wait". Или вы можете найти в Google, как связать предпочитаемый вами редактор кода с GIT.

Пример git rebase

Я хотел изменить последние 2 коммита, которые я сделал, поэтому я обрабатываю так:

  1. Показать текущие коммиты:
    #This to show all the commits on one line
    $git log --oneline
    4f3d0c8 (HEAD -> documentation) docs: Add project description and included files"
    4d95e08 docs: Add created date and project title"
    eaf7978 (origin/master , origin/HEAD, master) Inital commit
    46a5819 Create README.md
    
  2. Теперь я использую git rebaseдля изменения 2 последних сообщения о коммитах: $git rebase -i HEAD~2 он открывает редактор кода и показывает это:

    pick 4d95e08 docs: Add created date and project title
    pick 4f3d0c8 docs: Add project description and included files
    
    # Rebase eaf7978..4f3d0c8 onto eaf7978 (2 commands)
    #
    # Commands:
    # p, pick <commit> = use commit
    # r, reword <commit> = use commit, but edit the commit message
    ...
    

    Так как я хочу изменить сообщение коммита для этих 2 коммитов. Так что я буду печатать rили rewordвместо pick. Затем сохраните файл и закройте вкладку. Обратите внимание, что rebaseвыполняется в многошаговом процессе, поэтому следующим шагом является обновление сообщений. Также обратите внимание, что коммиты отображаются в обратном хронологическом порядке, поэтому последний коммит отображается в том же, а первый коммит в первой строке и т. Д.

  3. Обновите сообщения: обновите первое сообщение:

    docs: Add created date and project title to the documentation "README.md"
    
    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    ...
    

    сохранить и закрыть Редактировать второе сообщение

    docs: Add project description and included files to the documentation "README.md"
    
    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    ...
    

    сохранить и закрыть.

  4. К концу перебазирования вы получите такое сообщение: Successfully rebased and updated refs/heads/documentationэто означает, что вы добились успеха. Вы можете отобразить изменения:

    5dff827 (HEAD -> documentation) docs: Add project description and included files to the documentation "README.md"
    4585c68 docs: Add created date and project title to the documentation "README.md"
    eaf7978 (origin/master, origin/HEAD, master) Inital commit
    46a5819 Create README.md
    

    Желаю, чтобы это могло помочь новым пользователям :).

ДИНА ТАКЛИТ
источник
2

Для меня это было для удаления некоторых учетных данных из репо. Я попытался перебазировать и столкнулся с кучей, казалось бы, не связанных между собой конфликтов, когда пытался перебазировать - продолжай. Не пытайтесь перебазировать себя, используйте инструмент под названием BFG (brew install bfg) на Mac.

гранула
источник
0

Если вы еще не выдвинули коммиты, вы можете вернуться к предыдущему коммиту, используя git reset HEAD^[1,2,3,4...]

Например

git commit <file1> -m "Updated files 1 and 2"
git commit <file3> -m "Updated file 3"

Ой, забыл добавить file2 в первый коммит ...

git reset HEAD^1 // because I only need to go back 1 commit

git add <file2>

Это добавит file2 к первому коммиту.

rharvey
источник
0

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

Мой друг просто случайно натолкнулся на очень большие файлы (четыре автоматически сгенерированных файла размером от 3 до 5 ГБ каждый), а затем сделал еще несколько коммитов кода, прежде чем осознал проблему, которая больше git pushне работала!

Файлы были перечислены в списке, .gitignoreно после переименования папки контейнера они были открыты и зафиксированы! И теперь было еще несколько коммитов кода поверх этого, но pushон работал вечно (пытаясь загрузить ГБ данных!) И в конечном итоге потерпел неудачу из-за ограничений размера файлов Github .

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

Итак, решение, которое я придумал, было:

  1. Переименуйте текущую папку git в ~/Project-old.
  2. Снова клонируйте папку git из github (в ~/Project).
  3. Оформить заказ на ту же ветку.
  4. Вручную cp -rфайлы из ~/Project-oldпапки в ~/Project.
  5. Убедитесь, что массивные файлы, которые не нужны для проверки, mvотредактированы и .gitignoreправильно включены .
  6. Также убедитесь, что вы не перезаписываете .gitпапку в недавно клонированной ~/Projectстарой. Вот где живут журналы проблемной истории!
  7. Теперь просмотрите изменения. Это должен быть союз всех последних коммитов, исключая проблемные файлы.
  8. Наконец, внесите изменения, и это хорошо, когда вы будете pushизданы.

Самая большая проблема этого решения заключается в том, что оно имеет дело с ручным копированием некоторых файлов, а также объединяет все последние коммиты в один (очевидно, с новым хешем коммитов.) B

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

Помощь в
источник