Почему git rebase без аргументов работает так, как работает? - PullRequest
0 голосов
/ 01 июня 2018

Время от времени я выполняю git rebase без аргументов и обнаруживаю, что вместо перебазирования против моего сконфигурированного апстрима Git использовал опцию --fork-point и перебазировал против ... чего-то еще, что привело к исчезновению моих коммитов.

Это соответствует тому, что в документации для git rebase сказано:

Если не указано, восходящий поток настроен в ветви. .remote и branch. .merge будут использоваться (подробности см. В git-config [1]), и предполагается опция --fork-point.

Мой вопрос: Почему так работает?Лично я чувствую, что если я запускаю git rebase без параметров, я хочу выполнить ребазинг на настроенную ветку upstream.Если бы я хотел опровергнуть что-то еще, я бы так сказал.

Очевидно, что разработчики Git думают иначе, поэтому мне интересно, может ли кто-нибудь объяснить мышление таким образом, который поможет мне запомнить это?различие.

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

Формулировка вопроса («перебазирован против ... чего-то другого») предполагает, что вы либо не уверены, либо не согласны с тем, что должен делать fork-point.Если мы начнем с четкого представления о том, что он делает (и если мы предполагаем, что он работает должным образом и не имеет разрушительных побочных эффектов), то мотивация для его использования по умолчанию может показаться более ясной.

(Честно говоря, я никогда не удосужился выяснить, что делает fork-point, прежде чем взглянуть на этот вопрос. Лучшее объяснение, кажется, содержится в документации git merge-base - https://git -scm.com/docs/git-merge-base.)

Перед тем, как попасть в сорняки, два "больших изображения" наблюдения:

1) Я не думаю, что разработчики git согласятсячто использование fork-point означает, что вы «опровергаете что-то другое»;Я думаю, что они, вероятно, сказали бы, что вы все еще сопротивляетесь восходящему потоку, но более разборчивы в отношении того, что обязывает переписывать на новой базе.

2) Хотя fork-point не всегда может быть полезным,Мне не ясно, по какому сценарию это может привести к исчезновению ваших коммитов [1].Было бы интересно увидеть любые минимальные тестовые случаи, которые показывают проблемы (поскольку выше я упомянул «не принимайте никаких деструктивных побочных эффектов» как условие думать, что это разумное значение по умолчанию).

Так что вдаваясь в это ...

Что пытается сделать точка ветвления?

Короткий ответ: если коммит ранее был частью восходящего потока и был удален из восходящего потока через историюedit, затем --fork-point говорит rebase оставить этот коммит на том основании, что (1) он на самом деле не является частью ветви, (2) он уже был отклонен из апстрима и (3) мы, вероятно, не пытаемсяотмените переписывание чьей-либо истории.

Это делается путем вывода информации из журналов.Поскольку reflogs являются локальными и временными, это немного клудж;Ваша попытка перебазирования может получить иной результат, чем попытка кого-то другого выполнить такую ​​же перебазировку в, казалось бы, идентичном клоне репо.

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

Так зачем использовать его в качестве значения по умолчанию?

Я предполагаю, что суть в том, что разработчики предполагают, что если коммит был ранее в восходящем потоке и был удален извверх по течению, это удаление было окончательным.То, является ли это «обычно истиной», может зависеть от разработчика.

Странно то, что пример, используемый в merge-base документах (цитированных выше), кажется странным.Он показывает восходящий поток как origin/master, что подразумевает, что в какой-то момент master пульта дистанционного управления был переписан - что является ситуацией восстановления исходящего потока, которая обычно не рекомендуется.

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


[1] Я сделалпридумать один потенциальный случай, но я не уверен, что это тот случай, с которым вы сталкиваетесь.Если вы являетесь мастером, и вы начинаете разработку функции, и только после фиксации вы понимаете, что забыли создать ветку функции;поэтому вы создаете ветку «на месте», а затем перематываете master, чтобы не вносить изменения;тогда перебазирование функции в master с помощью fork-point может сделать неправильную вещь.

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

0 голосов
/ 01 июня 2018

Я сделал тест с 2 локальными репо.

#simulate a remote repo
git init server
cd server
> a
git add .
git commit -m 'a'
git branch new
> b
git add .
git commit -m 'b'
git checkout new
> c
git add .
git commit -m 'c'
git checkout master
cd -

И график git log --oneline --graph --decorate:

* 912e28a (HEAD -> master) b
| * 8c71449 (new) c
|/
* bd95493 a

Другой репозиторий, имитирующий локальное:

git clone server -- client
cd client
git reset HEAD^ --hard
> d
git add .
git commit -m 'd'

И график:

* 7173a5f (HEAD -> master) d
| * 912e28a (origin/master, origin/HEAD) b
|/
| * 8c71449 (origin/new) c
|/
* bd95493 a

origin/master является восходящей ветвью master.Теперь запустите git rebase, и график станет:

* 3bc57c5 (HEAD -> master) d
* 912e28a (origin/master, origin/HEAD) b
| * 8c71449 (origin/new) c
|/
* bd95493 a

График - это тот же результат, что и git rebase origin/master или git rebase origin/master master.

Затем повторите попытку с измененной веткой upstream:

#go back to the graph before the rebase
git reset 7173a5f --hard
#change the upstream
git config branch.master.merge refs/heads/new
git status
#try rebase again, without arguments
git rebase

График превращается в:

* b3bfd13 (HEAD -> master) d
* 8c71449 (origin/new) c
| * 912e28a (origin/master, origin/HEAD) b
|/
* bd95493 a

, как будто git rebase origin/new или git rebase origin/new master запущен.

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

Слияния коммитов исчезают без -p или --preserve-merges.Если в восходящем потоке уже есть эквивалентные коммиты, коммиты в текущей ветви тоже пропали.

...