Как изменить указанный коммит?
Я обычно представляю список коммитов на рассмотрение. Если у меня есть следующие коммиты:
HEAD
Commit3
Commit2
Commit1
... я знаю, что могу изменить коммит с головой git commit --amend
, Но как я могу изменить Commit1
учитывая, что это не HEAD
совершить?
20 ответов
Вы можете использовать git rebase, например, если вы хотите изменить обратно, чтобы зафиксировать bbc643cd
, бежать
$ git rebase --interactive 'bbc643cd^'
В редакторе по умолчанию измените pick
в edit
в строке, чей коммит вы хотите изменить. Внесите свои изменения, а затем зафиксируйте их в том же сообщении, что и раньше:
$ git commit --all --amend --no-edit
изменить коммит, и после этого
$ git rebase --continue
вернуться к предыдущему главному коммиту.
ВНИМАНИЕ: обратите внимание, что это изменит SHA-1 этого коммита, а также всех дочерних элементов - другими словами, это переписывает историю с этого момента. Делая это, вы можете сломать репо, если нажмете команду git push --force
Используйте удивительный интерактивный ребаз:
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
,
Интерактивный ребаз с --autosquash
это то, что я часто использую, когда мне нужно исправить предыдущие коммиты глубже в истории. Это существенно ускоряет процесс, который иллюстрирует ответ ZelluX, и особенно удобно, когда вам нужно отредактировать более одного коммита.
Из документации:
--autosquash
Когда сообщение журнала фиксации начинается с "squash! …" (Или "fixup! …"), И существует коммит, заголовок которого начинается с того же…, автоматически изменяйте список задач для rebase -i так, чтобы коммит пометка для сквоша наступает сразу после изменения коммита
Предположим, у вас есть история, которая выглядит так:
$ git log --graph --oneline
* b42d293 Commit3
* e8adec4 Commit2
* faaf19f Commit1
и у вас есть изменения, которые вы хотите внести в Commit2, а затем зафиксируйте изменения, используя
$ git commit -m "fixup! Commit2"
в качестве альтернативы вы можете использовать коммит-ша вместо сообщения фиксации, так "fixup! e8adec4
или даже просто префикс сообщения о коммите.
Затем инициируйте интерактивную перебазировку коммита до
$ git rebase e8adec4^ -i --autosquash
ваш редактор откроется с коммитами, уже правильно упорядоченными
pick e8adec4 Commit2
fixup 54e1a99 fixup! Commit2
pick b42d293 Commit3
все, что вам нужно сделать, это сохранить и выйти
На основании документации
Поправка к сообщению старых или нескольких сообщений коммита
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
Бежать:
$ 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
Полностью неинтерактивная команда(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-commit для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
это то, что делает все это неинтерактивным. Этот взлом я узнал из этого поста в блоге.
Если по какой-то причине вам не нравятся интерактивные редакторы, вы можете использовать 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
git stash
+ rebase
автоматизация
Когда мне нужно много раз модифицировать старый коммит для обзоров Геррита, я делаю:
git-amend-to() (
# 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"
)
Использование:
- изменить файл
git-amend-to $old_sha
Мне это нравится больше --autosquash
поскольку это не раздавливает другие несвязанные исправления.
Лучше всего использовать "Интерактивную команду перебазирования".
В
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
означает "п до ©, поэтому HEAD~n
будет список из "n" коммитов перед тем, в котором вы сейчас находитесь.
git rebase
имеет другую команду, например:
p
илиpick
сохранить фиксацию как есть.r
илиreword
: сохранить содержимое фиксации, но изменить сообщение фиксации.s
илиsquash
: объединить изменения этого коммита с предыдущим коммитом (коммит над ним в списке).... так далее.
Примечание. Чтобы упростить задачу, лучше заставить Git работать с вашим редактором кода. Например, если вы используете визуальный код, вы можете добавить вот так
git config --global core.editor "code --wait"
. Или вы можете поискать в Google, как связать предпочитаемый вами редактор кода с GIT.
Пример git rebase
Я хотел изменить последние 2 коммита, которые я сделал, поэтому обрабатываю так:
- Показать текущие коммиты:
#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
Сейчас использую
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
выполняется в многоэтапном процессе, поэтому следующим шагом будет обновление сообщений. Также обратите внимание, что фиксации отображаются в обратном хронологическом порядке, поэтому последняя фиксация отображается в этой, а первая фиксация в первой строке и так далее.Обновите сообщения: Обновите первое сообщение:
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. ...
сохранить и закрыть.
По окончании перебазирования вы получите такое сообщение:
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
Желаю, чтобы это помогло новым пользователям:).
Автоматическое интерактивное редактирование ребазирования с последующим коммитом, готовым к повторному выполнению
Я обнаружил, что исправляю прошлый коммит достаточно часто, поэтому я написал для него скрипт.
Вот рабочий процесс:
git commit-edit <commit-hash>
Это приведет вас к коммиту, который вы хотите отредактировать.
Фиксируйте и ставьте коммит так, как вам хотелось бы.
(Вы можете использовать
git stash save
сохранить любые файлы, которые вы не делаете)Повторить коммит с
--amend
Например:git commit --amend
Завершите перебазирование:
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
Изменение последней фиксации:
git commit --amend
// or
git commit --amend -m "an updated commit message"
Не изменяйте общедоступные коммиты Исправленные коммиты на самом деле являются совершенно новыми коммитами, и предыдущий коммит больше не будет находиться в вашей текущей ветке.
Например, если вы хотите изменить последние три сообщения коммита или любое из сообщений коммита в этой группе, вы указываете в качестве аргумента git rebase -i родительский элемент последнего коммита, который вы хотите отредактировать, то есть HEAD~2. ^ или ГОЛОВА~3. Может быть легче запомнить ~3, потому что вы пытаетесь отредактировать последние три коммита, но имейте в виду, что на самом деле вы указываете четыре коммита назад, родителя последнего коммита, который вы хотите отредактировать:
$ git rebase -i HEAD~3
Чтобы получить неинтерактивную команду, поместите скрипт с этим содержимым в вашу переменную 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>
, Конечно, он все равно будет интерактивным, если у вас возникнут конфликты.
Пришел к этому подходу (и это, вероятно, точно так же, как с использованием интерактивного ребазинга), но для меня это довольно просто.
Примечание: я представляю этот подход для иллюстрации того, что вы можете сделать, а не для повседневной альтернативы. Так как у него много шагов (и, возможно, несколько предостережений).
Скажем, вы хотите изменить коммит 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)
Rebase 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 при ребазинге.
Примечание: все хеши коммитов меняются, начиная с коммита, который мы изначально намеревались изменить.
Я делаю следующее, включая изменение даты и времени локальных коммитов:
git rebase -i HEAD~6
~6
это количество отображаемой истории коммитов.
- Меняться от
pick
кedit
коммиты для редактирования. - Затем я сохраняю и выхожу (в Ubuntu:
Ctrl+O
сохранить иCtrl+X
выйти) -
- Затем я запускаю:
git commit --amend --date="2022-09-02T19:10:04" -m "NEW_MSG"
- Затем я запускаю:
-
- Если редактирование открыто, просто сохраните и выйдите.
-
- Затем, чтобы подтвердить и перейти к следующему коммиту или закончить, если он последний, я выполняю:
git rebase --continue
- Затем, чтобы подтвердить и перейти к следующему коммиту или закончить, если он последний, я выполняю:
Если есть еще коммиты для редактирования, это повторяется с пункта 1
Наконец, я проверяю изменения и, если все в порядке, я делаюpush
Я решил это,
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-дерева неприемлемым способом приведет к конфликтам, о которых вы не знаете. если вы хотите сохранить свое дерево в чистоте с меньшим количеством коммитов, можете попробовать это, и если его небольшая команда в противном случае его не желательно.....
Если вы хотите только перефразировать старое сообщение коммита без изменения хэшей в ветке, вы можете использовать:
git replace --edit <commit>
Измененные ссылки затем необходимо будет отправить и получить явно с помощью:
git push origin 'refs/replace/*'
git fetch origin 'refs/replace/*:refs/replace/*'
Для меня это было для удаления некоторых учетных данных из репо. Я попытался перебазировать и столкнулся с кучей, казалось бы, не связанных между собой конфликтов, когда пытался перебазировать - продолжить. Не пытайтесь перебазировать себя, используйте инструмент под названием BFG (brew install bfg) на Mac.
Что ж, это решение может показаться очень глупым, но может спасти вас в определенных условиях.
Мой друг просто случайно столкнулся с очень большими файлами (четыре автоматически сгенерированных файла размером от 3 до 5 ГБ каждый), а затем сделал дополнительный код поверх этого, прежде чем осознал проблему, заключающуюся в том, чтоgit push
больше не работает!
Файлы были перечислены в .gitignore
но после переименования папки контейнера они были раскрыты и зафиксированы! А теперь поверх этого было еще несколько коммитов кода, ноpush
работал вечно (пытался загрузить ГБ данных!) и, наконец, завершился ошибкой из-за ограничений на размер файла Github.
Проблема с интерактивным перебазированием или чем-то подобным заключалась в том, что они имели дело с копанием в этих огромных файлах и требовали вечности, чтобы что-то сделать. Тем не менее, проведя почти час в интерфейсе командной строки, мы не были уверены, действительно ли файлы (и дельты) удалены из истории или просто не включены в текущие коммиты. Толчок тоже не работал, и мой друг действительно застрял.
Итак, решение, которое я придумал, было:
- Переименовать текущую папку git в
~/Project-old
. - Снова клонируйте папку git из github (чтобы
~/Project
). - Касса в том же отделении.
- Вручную
cp -r
файлы из~/Project-old
папку в~/Project
. - Убедитесь, что массивные файлы, которые не нужно возвращать,
mv
ed, и включен в.gitignore
должным образом. - Также убедитесь, что вы не перезаписываете
.git
папка в недавно клонированном~/Project
по старому. Вот где живут журналы проблемной истории! - Теперь просмотрите изменения. Это должно быть объединение всех последних коммитов, исключая проблемные файлы.
- Наконец зафиксируйте изменения, и хорошо быть
push
изд.
Самая большая проблема с этим решением заключается в том, что оно связано с ручным копированием некоторых файлов, а также объединяет все недавние коммиты в один (очевидно, с новым хешем фиксации). B
Его большие преимущества заключаются в том, что он очень четкий на каждом этапе, он отлично работает с огромными файлами (а также с конфиденциальными) и не оставляет никаких следов в истории!
Если вы еще не отправили коммиты, вы можете вернуться к предыдущей фиксации, используя 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 к первой фиксации.
У меня была такая же проблема, и это:
- Сначала продублировал ветку как
x
, - Затем жесткий отдых туда, куда вы хотите вернуться
- Затем внесите новые изменения
- После этого выберите все остальные изменения из исходной ветки.
- Оформить исходную ветку
- Сбросить исходную ветку перед измененной реверсией
- перебазировать в ветку x
Мой журнал git:
git checkout -b x 77164a510f1c17ed650b87c2ebf0f7762ac6b2a2 --
git reset --hard 0d038b5e3e3e2adef4bd6aab7653f922c3fdc63f
git add --ignore-errors -A -f -- src/Mores.Warehouse.Core.Api.ClientSdk/Mores.Warehouse.Core.Api.ClientSdk.csproj
git commit -F C:\Users\Hassan\AppData\Local\Temp\git-commit-msg-.txt --amend --
git cherry-pick 77164a510f1c17ed650b87c2ebf0f7762ac6b2a2
git checkout feature/MOR-2947 --
git reset --hard 0d038b5e3e3e2adef4bd6aab7653f922c3fdc63f
git rebase x