Git разветвляется самостоятельно - PullRequest
0 голосов
/ 04 октября 2018

Я использую git в репозитории, для которого я являюсь единственным участником.Хранилище размещено на Github.По какой-то причине git иногда появляется на Github, и я ничего не меняю.Я делаю изменения в этом репо только на одном компьютере и ничего не изменяю на Github.Тем не менее, как вы можете видеть из этого сокращенного выбора git log --oneline --decorate --graph --all, мне, кажется, приходится делать это случайно.Коммит 271056c дублируется в cfacddf на Github.

Что может вызвать это?Это ошибка?

Возможная теория, которую я сейчас рассматриваю: может ли это быть результатом git commit --amend?

Вывод git log --oneline --decorate --graph --all:

*   d030d88 (HEAD -> master, origin/master, origin/HEAD) Merge branch 'master' of ***
|\
| * cfacddf Fixed a few things:
* | 798afef modified:   tasks.txt
* | 2c19ea0 Paginated:
* | 271056c Fixed a few things:
|/
* 63a429c Added lock icon to annotation headers

Выводgit log:

commit d030d8820456b0f129d2d3e5167ed88f87ebe028
Merge: 798afef cfacddf
Author: ***
Date:   Wed Oct 3 16:49:00 2018 -0400

    Merge branch 'master' of https://github.com/malan88/icc

commit 798afefabe24027a955853771072755c08318b47
Author: Michael Alan <michaelalantarpon@gmail.com>
Date:   Wed Oct 3 16:48:54 2018 -0400

    modified:   tasks.txt

commit 2c19ea0b735d148f0057852c196254c4258c2c6b
Author: ***
Date:   Wed Oct 3 16:42:20 2018 -0400

    Paginated:

    - Author index
    - Book index
    - User Annotations
    - Tag index

commit 271056c1c34444dbb3b8c2b6a67efae67f27b44b
Author: ***
Date:   Wed Oct 3 15:24:14 2018 -0400

    Fixed a few things:

    - hash_id bug
    - line_number_form on read.html bug
    - horribly inefficient permissions check on line edits on read.html
    - Added lock change mechanism for when admin doesn't want to edit
        annotation
    - cleaned up some bad whitespace
    - Bug that didn't include query parameters in next parameter (e.g.
    pagenumbers, etc)

commit cfacddfb5395e0fa3676fbc1e19457c45c7c3529
Author: ***
Date:   Wed Oct 3 15:24:14 2018 -0400

    Fixed a few things:

    - hash_id bug
    - line_number_form on read.html bug
    - horribly inefficient permissions check on line edits on read.html
    - Added lock change mechanism for when admin doesn't want to edit
        annotation
    - cleaned up some bad whitespace
    - Bug that didn't include query parameters in next parameter (e.g.
    pagenumbers, etc)

commit cfacddfb5395e0fa3676fbc1e19457c45c7c3529
Author: ***
Date:   Wed Oct 3 15:24:14 2018 -0400

    Fixed a few things:

    - hash_id bug
    - line_number_form on read.html bug
    - horribly inefficient permissions check on line edits on read.html
    - Added lock change mechanism for when admin doesn't want to edit
        annotation
    - cleaned up some bad whitespace

commit 63a429c828cec06fa30e4994f3912fab387c7a4c
Author: ***
Date:   Wed Oct 3 15:21:58 2018 -0400

    Added lock icon to annotation headers

1 Ответ

0 голосов
/ 04 октября 2018

Давайте начнем с этого:

Возможная теория, которую я сейчас рассматриваю: может ли это быть результатом git commit --amend?

Да.

Теперь давайте вернемся к этому, потому что здесь есть скрытое предположение, которое является ключевым фактором:

Я использую git в репозитории, для которого я являюсь единственным участником.Хранилище размещено на GitHub.

Это не совсем верно.Здесь вы имеете в виду, что на GitHub есть репозиторий a .Это не репозиторий : это один из нескольких или многих.В этом случае это один из двух.Другой на вашей собственной машине!

Для правильного объяснения, смотрите любой из моих более длинных ответов.См. Также веб-сайт Think Like (a) Git , который имеет много важных сведений.Но, для краткости, помните, что здесь есть два репозитория: ваш и Git-репозиторий на GitHub.

Когда вы делаете коммит, он однозначно идентифицируется по своему хэш-идентификатору - большой некрасивой строке шестнадцатеричных цифр, напримеркак cfacddfb5395e0fa3676fbc1e19457c45c7c3529.Это то, что ваш Git хранит в названии вашей ветки master.Каждый коммит также хранит хэш-идентификатор своего предыдущего или родительского коммита (ов).Фиксация слияния - это фиксация как минимум с двумя родителями.Когда имя ветви или коммит хранит хэш-идентификатор коммита, мы говорим, что это имя или этот коммит указывает на целевой коммит.

Мы можем нарисовать такие вещи как (Горизонтально ориентированные) графики с последним коммитом вправо:

...<-F  <-G  <-H   <--master

Git присоединяет имя HEAD к имени ветви, так что если у вас есть несколько имен веток, он знает, какая из них является текущей веткой.Стрелки внутри коммитов не могут измениться - ничего внутри любой коммит не может когда-либо измениться, поэтому нам не нужно рисовать внутренние стрелки:

...--F--G--H   <-- master (HEAD)

Когдавы запускаете git commit, обычная процедура состоит в том, чтобы заморозить все, что есть в вашем индексе прямо сейчас, в новый снимок, сделать родительский снимок текущим коммитом , используя указатель из имени ветви, на которое HEAD присоединено:

...--F--G--H--I

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

...--F--G--H--I   <-- master (HEAD)

Как git commit --amend работает

Мы только что увидели, что git commit:

  1. замораживает текущий индекс в снимок;
  2. записываетновый коммит с текущим коммитом в качестве родителя;
  3. записывает хэш нового коммита в текущую ветвь.

Все, что делает --amend, это изменение, чтобы изменить шаг 2:вместо использования текущего коммита в качестве родителя нового коммита, --amend usES родителей текущего коммита в качестве родителей нового коммита.(Если существует несколько родителей - если текущий коммит является слиянием - новый коммит получает всех родителей текущего коммита. Если это обычный однократный коммит без слияния, новый коммит получает одного нового родителя.) Поэтому вместопереходя от ...-F-G-H к ...-F-G-H-I, мы получаем:

          H
         /
...--F--G--I   <-- master (HEAD)

То есть --amend выталкивает текущий коммит с пути .

Thisотлично работает, если вы не нажали

Если вы нигде не нажимали коммит H, его изменение теперь работает нормально.Новый коммит I вступает во владение;коммит H исчезает, больше никогда его не увидеть.(Вы можете найти его в своем собственном репозитории некоторое время - по крайней мере, 30 дней по умолчанию, пока не истечет срок действия записей reflog, которые помнят его. Но он не отображается в обычном выводе git log.)

Ноон потерпит неудачу, если у вас есть

Но если у вас есть отправленный коммит H в другой Git, например, в хранилище, которое вы храните на GitHub, то каждый раз, когда вы обращаетесь к с ними , они предложат вам снова зафиксировать H, как важный коммит в их master ветви.Это то, что случилось в этом случае.

У вас был пуshed commit H для GitHub.Затем ваш Git вытолкнул ваш H с пути, как указано выше, но GitHub все еще имел H.Ваш Git помнит это, хотя, если ваш Git забыл или вы стерли его память, ваш Git будет напоминаться при следующем вызове Git на Git на GitHub.Итак, теперь у вас есть это:

          H   <-- origin/master
         /
...--F--G--I   <-- master (HEAD)

С этого момента, когда вы работаете в своем хранилище, коммит H остается видимым.Вы сделали коммиты J (271056c1c34444dbb3b8c2b6a67efae67f27b44b) и K (798afefabe24027a955853771072755c08318b47):

          H   <-- origin/master
         /
...--F--G--I--J--K   <-- master (HEAD)

В этот момент вы запустили git pull, когда ваш Git вызывал Git на GitHubи получите любые новые коммиты от GitHub (их не было) и обновите свой origin/master, чтобы он соответствовал master (все еще указывая на коммит H).Затем ваш git pull получил ваш Git merge их коммит H с вашим коммитом K, создав новый коммит с двумя родителями L:

          H_  <-- origin/master
         /  `----__
...--F--G--I--J--K-=L   <-- master (HEAD)

, и эточто ты видишь сейчас.(Ну, сейчас вы также попросили GitHub Git установить для их master значение L, что они и сделали, так что origin/master вашего хранилища Git тоже перейдет на L.)

Чтобы исправить это, вы должны заставить всех остальных Git забыть H

После того, как вы "исправите" H, вы должны найти все другие репозитории Git, которые имели H и убедить их использоватьI вместо.В этом случае задействован только один другой Git: тот, что на GitHub.Вы можете запустить:

git push origin master

, который заставит ваш Git вызвать Git на GitHub и вежливо попросить, чтобы они изменили свой master, чтобы он указывал на ваш коммит замены I.Но если вы сделаете это, вы обнаружите, что они говорят нет, я не буду этого делать, потому что это потеряло бы коммит H. Форма этой жалобы:

! [rejected]        master -> master (non-fast-forward)

В этом случае вы знаете, в чем проблема, и что вы хотите их потерять (забыть) совершить H.Таким образом, вы можете использовать git push --force или более изящный вариант git push --force-with-lease.

. Они преобразуют ваш запрос (, пожалуйста, обновите master) в команду: обновите свойmaster! GitHub все еще может отказаться (и будет, если у вас нет прав на это), но в целом они будут подчиняться команде, в которой они отклонили запрос.Опция --force-with-lease работает как проверка безопасности: вместо того, чтобы просто сказать сделать это в любом случае , ваш Git говорит им: Я думаю, что ваш мастер настроен на,Если это так, замените его.Если нет, дайте мне знать. Это то, что вы можете использовать в общем хранилище, в случае, если другие люди также подталкивают к GitHub master.

...