Git push single commit не работает - PullRequest
0 голосов
/ 25 июня 2018

Я пытаюсь выдвинуть только коммит с идентификатором 9973b14ca19e4571046d8d25bc986ec07199e39c .

git push bbef 9973b14ca19e4571046d8d25bc986ec07199e39c:refs/heads/feature/25062018_offline-seite_ef

Я вошел в Bitbucket, чтобы создать запрос на получение, но я заметил, что существует несколько коммитов, хотя это новая удаленная ветвь.

Итак, я удалил удаленную ветку в bitbucket и снова нажал ее, тот же результат ...

enter image description here

Почему это не работает и как я могу выдвинуть только один коммит вместо нескольких? Почему это происходит?

Ответы [ 2 ]

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

Когда вы запускаете git push, у вас есть предложение Git для другого Git:

  • определенный коммит (по хеш-идентификатору или имени), плюс
  • вся история коммитов, ведущая к этому конкретному коммиту.

(Другой Git скажет вашему Git, когда прекратить предлагать предыдущие коммиты, потому что у другого Git они уже есть.) Это именно то, что вы видите.

Это поможет остановить, выполнить резервное копирование и нарисовать график фиксации (или хотя бы его часть). Вы можете запустить git log --graph - я обычно предпочитаю вариант «помощь от СОБАКИ», git log --all --decorate --online --graph, A ll D ecorate O neline G raph = ADOG - чтобы Git нарисовал график довольно грубо для вас. Некоторые графические интерфейсы рисуют график по-своему.

Помните, что в Git имя ветви - это просто удобочитаемое имя для одного (1) хеш-идентификатора. Каждый коммит имеет уникальный хэш-идентификатор, назначаемый во время выполнения коммита, но каждый коммит также содержит хэш-идентификатор своих родительских коммитов - обычно один или два для коммитов слияния - и эти строки фиксируют коммиты вместе в цепочки, которые разветвляются и при коммитах слияния сливаются обратно вместе. Не имеет значения, рисуете ли вы график вертикально, с новыми коммитами вверху, как это делает Git, или горизонтально, с более новыми коммитами справа, как обычно я делаю в публикациях StackOverflow. На самом деле важно рисовать график , потому что, как только вы это сделаете, то, что делает Git, становится очевидным:

A  <-B  <-C   <--master

Это представляет общую сумму коммитов в крошечном репозитории с тремя коммитами. Каждая заглавная буква обозначает фактический хэш-идентификатор. Ветвь name , master, запоминает фактический хэш-идентификатор last commit, commit C. Сам коммит C запоминает хэш-идентификатор своего предыдущего или родительского коммит B. B запоминает хэш-идентификатор A, и, поскольку A - самый первый коммит, у него нет родителя.

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

...--*--*------o--o---o--X--o--o   <-- branch
         \           /
          o--o------o

, где * представляет коммит, который уже есть на сервере - вы уже отправили его или, например, получили с сервера, а o представляет коммит, который у вас есть, которого у него нет. В этот момент, если вы нажмете третий коммит (вправо) вдоль нижнего ряда, они получат три коммита: все три из нижнего ряда. Это потому, что, начиная с этого коммита и работая в обратном направлении, требуется три коммита, чтобы ваш новый соединился со своими существующими. Если вы нажмете одну из двух фиксаций в верхнем ряду сразу после *, ваш Git отправит одну или две фиксации. Если вы выдвигаете коммит, который приходит после слияния, ваш Git будет выдвигать как минимум шесть коммитов. Нажатие коммита X здесь толкает семь: X само по себе и необходимое число предшествующих шести.

Если вы хотите выдвинуть один коммит, который добавляет второй коммит со звездочкой, вы должны сначала сделать единственный коммит, который добавляет второй коммит со звездочкой:

          Y   <-- new-name
         /
...--*--*------o--o---o--X--o--o   <-- branch
         \           /
          o--o------o

Если у вас есть эта настройка, если вы нажимаете коммит Y, у них уже есть отмеченные коммиты (конечно), так что ваш Git фактически будет толкать один коммит, а именно коммит Y.

Как сделать этот единственный коммит

Чтобы создать commit Y, сначала вам нужно 1 , чтобы создать новое имя ветки, указывающее на окончательный коммит *. Найдите его хэш-идентификатор или любое другое имя, которое однозначно его идентифицирует, и проверьте этот конкретный коммит и создайте для него имя:

git checkout -b new-name <hash-id>

этот отпускСам график остается неизменным, но новое имя указывает на этот коммит. 2 Команда git checkout -b помещает вас в эту новую ветку одновременно с созданием имени. (Обратите внимание, что в этот момент отправка новой ветви на сервер отправит серверу no коммитов, а также просто создаст имя на сервере.)

        /----------------------------- new-name (HEAD)
        |
        v
...--*--*------o--o---o--X--o--o   <-- branch
         \           /
          o--o------o

Теперь вы можете запустить:

git cherry-pick <hash-of-desired-commit-X>

, который в данном случае:

git cherry-pick 9973b14ca19e4571046d8d25bc986ec07199e39c

Это заставляет Git проверить коммит 9973b14ca19e4571046d8d25bc986ec07199e39c. Git извлечет моментальный снимок своего родительского коммита и моментальный снимок этого коммита и изменит их (а-ля git diff). 3 Затем Git применит любые изменения в текущем коммите, чтобы сделать новый коммит, который является копией из X:

          Y  <-- new-name (HEAD)
         /
...--*--*------o--o---o--X--o--o   <-- branch
         \           /
          o--o------o

и теперь у вас есть то, что вам нужно: коммит, который можно выдвинуть сам, потому что история Y - его родитель, прародитель и т. Д. - уже существует на сервере .


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

2 Вы также можете создать имя ветви, используя git branch:

git branch new-name <hash-id>

Затем вам нужно запустить git checkout new-name, чтобы получить на этой ветке, то есть присоединить ваш HEAD к этому имени.

3 С технической точки зрения cherry-pick - это операция слияния, которая приводит к фиксации без слияния: merge-as-a-verb, для слияния , но не как прилагательное или существительное. Это позволяет черрику работать в ситуации, когда простой патч не сработает. Однако это конкретное осложнение здесь в основном не имеет значения: оно имеет значение только в том случае, если выбор вишни приводит к конфликту слияния.

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

Вы думаете, что вы выдвинули только один коммит, но фактически вы выдвинули много коммитов вместо этого. Фиксация коммита 9973b14 зависит от других коммитов, которых нет в ветке feature / 25062018_offline-seite_ef, поэтому они будут объединены. Так работает Git.

Вам необходимо создать локальную ветвь на основе ветки remote feature / 25062018_offline-seite_ef, затем cherrypick коммита 9973b14 и затем нажать на удаленную.

...