Я пытался изменить временную метку нефиксированного коммита и допустил ошибку (сделал новую ветвь и слияние вместо rebase --continue), что привело к дублированию еще не переданных коммитов.Вот скрипт bash, который имитирует проблему, скажем test.sh
:
rm -rf mytestgit
mkdir mytestgit
cd mytestgit
git init
git config user.email "you@example.com"
git config user.name "Your Name"
SLEEPTIME=5
git commit --allow-empty -m 'first commit'
echo " (... wait ...) "; sleep $SLEEPTIME
git commit --allow-empty -m 'second commit'
echo " (... wait ...) "; sleep $SLEEPTIME
THIRDC=$(git commit --allow-empty -m 'third commit')
echo $THIRDC
echo " (... wait ...) "; sleep $SLEEPTIME
git commit --allow-empty -m 'fourth commit'
git status
git --no-pager log --graph --abbrev-commit --all --decorate --pretty=format:"%h%x09%an%x09%ad%x09%s %d" ; echo # add '\n' at end
GLOGLAST=$(git --no-pager log -1 --graph --abbrev-commit --all --decorate --pretty=format:"%h%x09%an%x09%ad%x09%s %d")
IFS=+ read left SPLITGLLA <<< "$GLOGLAST"
IFS=" " read SPLITGLL right <<< "$SPLITGLLA" # this is TAB here, not space, for IFS
TIMEZONE=${SPLITGLL[0]}
SPLITTC=(${THIRDC//]/ })
THIRDCHASH="${SPLITTC[1]}"
THIRDCUTS=$(git show -s --format=%ct $THIRDCHASH)
THIRDCUTSNEW=$((THIRDCUTS-3))
echo "Third commit hash: $THIRDCHASH, Unix timestamp $THIRDCUTS, timezone +$TIMEZONE, new Unix timestamp (three seconds earlier) $THIRDCUTSNEW"
echo
# cd mytestgit # already in
# here choose $THIRDCHASH with e, saving and closing text editor
git rebase $THIRDCHASH^ -i --keep-empty
GIT_COMMITTER_DATE="$THIRDCUTSNEW +$TIMEZONE" git commit --amend --no-edit --allow-empty --date "$THIRDCUTSNEW +$TIMEZONE"
# here the mistake
git checkout -b newbranch
git checkout master
git merge newbranch
git branch -d newbranch
# check final state
git --no-pager log --graph --abbrev-commit --all --decorate --pretty=format:"%h%x09%an%x09%ad%x09%s %d" ; echo # add '\n' at end
Когда я запускаю этот скрипт, я получаю, скажем, такой вывод:
Initialized empty Git repository in /tmp/mytestgit/.git/
[master (root-commit) 1a5fa9a] first commit
(... wait ...)
[master f6b51cc] second commit
(... wait ...)
[master f9871cc] third commit
(... wait ...)
[master cfd0208] fourth commit
On branch master
nothing to commit, working directory clean
* cfd0208 Your Name Tue Oct 2 13:05:00 2018 +0200 fourth commit (HEAD, master)
* f9871cc Your Name Tue Oct 2 13:04:55 2018 +0200 third commit
* f6b51cc Your Name Tue Oct 2 13:04:50 2018 +0200 second commit
* 1a5fa9a Your Name Tue Oct 2 13:04:45 2018 +0200 first commit
Third commit hash: f9871cc, Unix timestamp 1538478295, timezone +0200, new Unix timestamp (three seconds earlier) 1538478292
Stopped at f9871cca92f2e3da587fa8b16021f8e52976c8d9... third commit
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
... thenна ребазе у меня это есть в автозапускаемом текстовом редакторе (изменив первый pick
на e
):
e f9871cc third commit
pick cfd0208 fourth commit
# Rebase f6b51cc..cfd0208 onto f6b51cc
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
... который я сохраняю, затем выхожу из текстового редактора -скрипт продолжается с:
[detached HEAD 63e35fe] third commit
Switched to a new branch 'newbranch'
Switched to branch 'master'
... и при ошибочном слиянии я получаю это в автозапускаемом текстовом редакторе:
Merge branch 'newbranch'
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
... который я сохраняю безизменения, затем выйдите из текстового редактора - и сценарий завершится с отображением конечного состояния:
Already up-to-date!
Merge made by the 'recursive' strategy.
Deleted branch newbranch (was 63e35fe).
* 9b1ac28 Your Name Tue Oct 2 13:05:36 2018 +0200 Merge branch 'newbranch' (HEAD, master)
|\
| * 63e35fe Your Name Tue Oct 2 13:04:52 2018 +0200 third commit
* | cfd0208 Your Name Tue Oct 2 13:05:00 2018 +0200 fourth commit
* | f9871cc Your Name Tue Oct 2 13:04:55 2018 +0200 third commit
|/
* f6b51cc Your Name Tue Oct 2 13:04:50 2018 +0200 second commit
* 1a5fa9a Your Name Tue Oct 2 13:04:45 2018 +0200 first commit
Итак, теперь у меня есть дублирующие коммиты (63e35fe «третий коммит»), а также коммит слияния (9b1ac28)"Merge branch 'newbranch'") вместо дублирующего "четвертого коммита".
По сути, у меня второй и первый коммит уже перенесены в онлайн-репо, но третий и четвертый еще не выдвинуты.
Как я могу удалить дубликат (63e35fe «третий коммит», который в итоге оказался сизмененная временная метка вместо оригинального f9871cc "третий коммит") и дополнительного слияния (9b1ac28 "ветвь слияния" newbranch "), поэтому я не заканчиваю тем, что толкнул их в репо?
Или, другими словами, как я могу восстановить состояние репо до запуска команды git rebase $THIRDCHASH^ -i --keep-empty
, чтобы я мог перезапустить его снова и правильно завершить его с помощью git rebase --continue
вместо слияния,чтобы я мог нажать «оригинальные» коммиты (а не дубликаты / дополнения) онлайн?