Есть ли способ переместить коммит в журнал git? - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть коммит, который я выбрал из другой ветки (не уверен, что другая ветка релевантна), но он появляется через 'git log', что добавляет этот коммит в конец / вершину истории, хотяон имеет правильную дату и время, когда был сделан коммит.Есть ли способ переместить этот коммит обратно в журнал, чтобы дата / время имели смысл по сравнению с другими коммитами?

Ответы [ 3 ]

0 голосов
/ 20 сентября 2018

Будьте осторожны с тем, что вы просите.git log ложь , но это хорошая вещь!

ОК, "ложь" - преувеличение.Но стоит помнить, git log показывает вам что-то , но это намеренно глазок в реальность, а не вся реальность сразу.Это немного похоже на утверждение, что время - это способ природы предотвратить все происходящее одновременно : git log должен показать, что вы совершаете по одному за раз, но они все там.

Коммиты

Во-первых, коммиты имеют две метки времени, а не одну.По умолчанию git log показывает дату автора.Аргументы --since и --until смотрят дату создания.Для большинства коммитов две метки времени совпадают, и это не имеет значения.Для выбранных вишней коммитов или коммитов, сделанных кем-то отличным от оригинального автора, иногда имеет значение .Вот небольшой вывод git log --pretty=fuller, показывающий такой коммит:

commit 6c6ce21baa9b50d394bb8ed9878944504ffd57d8
Author:     Eric Sunshine <sunshine sunshineco.com>
AuthorDate: Fri Aug 31 04:33:42 2018 -0400
Commit:     Junio C Hamano <gitster pobox.com>
CommitDate: Fri Aug 31 12:05:24 2018 -0700

    config.mak.uname: resolve FreeBSD iconv-related compilation warning

    OLD_ICONV has long been needed by FreeBSD so config.mak.uname defines
    it unconditionally. However, recent versions do not need it, and its
    presence results in compilation warnings. Resolve this issue by defining

Второй - и, возможно, на самом деле более важный - каждый коммит Git хранит, как часть своих собственных данных, хэш-идентификатор своего parent commit или commit.Это означает, что коммиты имеют отношения родитель / потомок.Истинное имя любого коммита Git - это его большой уродливый хеш-идентификатор, такой как 6c6ce21... выше.

Мы можем найти родителя (ей) коммита, используя git rev-parse, или посмотрев прямо наобъект фиксации:

$ git rev-parse 6c6ce21baa9b50d394bb8ed9878944504ffd57d8^1
53f9a3e157dbbc901a02ac2c73346d375e24978c
$ git cat-file -p 6c6ce21baa9b50d394bb8ed9878944504ffd57d8
tree 1832fd8f6315732daca5c0523a951d40a8ee7fb2
parent 53f9a3e157dbbc901a02ac2c73346d375e24978c
author Eric Sunshine ...[snip]

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

Давайте нарисуем простую строку коммитов, дав им однобуквенные имена вместо больших уродливых хеш-идентификаторов, где каждый коммит имеет одного родителя и одного потомка, кромедля самого первого или root коммита - у которого нет родителя - и последнего, или tip commit, у которого нет потомка:

A  <-B  <-C  <-D  <-E  <-F  <-G

Если мыначинаем с конца - что обычно делает Git - у нас есть коммит G в руке.Итак, git log идет впереди, начиная с коммита, который он сейчас имеет в руке, и показывая коммит G.G помните F большой уродливый хеш-идентификатор, так что теперь git log возвращается на один шаг назад и показывает F;затем он возвращается обратно к E, D и так далее, пока не достигнет A.Мы говорим, что каждый коммит указывает на своего родителя, и Git следует этим указателям.

Настоящий трюк Git в том, что он каким-то образом находит G.На этой диаграмме нет ничего, указывающего на G, так как Git может его найти?Ответ: названия филиалов .У нас есть имя ветки вроде master, указывающее на коммит G:

A--B--C--D--E--F--G   <-- master

Поскольку коммиты заморожены, и я немного ленив, :-) Я опустил внутренние стрелки.Мы знаем, что все они указывают назад, поэтому они нам не нужны: линии подойдут. name master позволяет Git найти коммит G.Начиная с G, Git возвращается к F, затем к E и т. Д.

Самое интересное в этом - это когда мы добавляем новый коммит.,Допустим, мы git checkout master, так что мы извлекли G.Затем мы делаем некоторую работу и запускаем git add и git commit.Это делает новый коммит с новым большим уродливым хеш-идентификатором, но мы просто назовем его H.H будет указывать на, т. Е. Содержать большой некрасивый хеш-идентификатор, commit G:

...--G   <-- master
      \
       H

Последнее, что делает Git, - это запись хеш-идентификатора H вимя master, поэтому master теперь указывает на H (и мы можем снова нарисовать линию прямо):

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

Это означает, что коммиты никогда не меняются (они не могут), но имена веток все время меняются! Что Git меняет, это не коммиты, а names .

Ветвление и слияниеи как это влияет и git log

ОК, таку нас есть несколько хороших прямых строк истории коммитов, но что теперь произойдет, когда мы создадим несколько веток и затем объединим их?Ответ в том, что Git делает коммитов слияния , которые просто коммитят с двумя родителями:

          I--J   <-- branch-A
         /
...--G--H
         \
          K--L   <-- branch-B

Если у нас есть Git слияния двух, мы получаем новыйcommit M, у которого оба J и L в качестве его родителей:

          I--J
         /    \
...--G--H      M
         \    /
          K--L

(Упражнение: здесь я удалил все имена веток.Какие имена веток обновляет Git? Как Git узнает, когда есть два имени branch-A и branch-B, над какой ветвью вы работаете? Решение этого упражнения научит вас многому о Git.Или читерство с веб-сайтом, о котором я упоминаю ниже. :-))

Теперь, когда идет git log, он покажет коммит M, но затем - какой коммит должен показать следующий, J, или L?

Необходимо показать оба коммитов.В идеале, он должен показывать их одновременно, но он не может .Он должен выбрать один, чтобы показать первым.(Время препятствует тому, чтобы все происходило одновременно.) Это когда - и почему - git log имеет ложь: он должен сначала показать один, даже если J и L действительно "вв то же время "как раз перед M.

Здесь git log имеет несколько флагов, сообщающих ему как лгать .Ложь по умолчанию - использовать то, что вы хотите: штамп с датой!Но это штамп даты, который git log не показывает вам по умолчанию, то есть дату коммиттера, здесь.Добавление --author-date-order заставляет Git выбирать дату автора вместо даты коммиттера.Обратите внимание, что это влияет только на выбор, когда git log имеет более одного коммита для отображения прямо сейчас - что верно, когда он показывает, скажем, J вместо L.После этого у него все еще есть два коммита для показа, а именно I и L.Он выберет один из этих двух вариантов, используя ваш вариант сортировки, и еще раз будет отображать два коммита: H и L или I и K, в зависимости от того, какой из них только что показан.

Это слишком сложно

Ну, да, это так.К сожалению, это реальность.Есть способ заставить git log до нарисовать график , а также показать коммиты, используя git log --graph.Это не всегда полезно, но когда это полезно, это чрезвычайно полезно.

Более подробно об этом см. Веб-сайт Думайте, как (а) Git .Вам нужно , чтобы знать все это, в конце концов, чтобы эффективно использовать Git.До тех пор, однако, тот факт, что ложь git log - она ​​скрывает всю эту сложность по умолчанию, - это хорошо.

0 голосов
/ 19 февраля 2019

Я не думаю, что есть.Но это должно быть хорошо.Помните, что в «git log» или в истории редакций он описывает, что соавторы сделали с хранилищем.То, что на самом деле делает «git cherry-pick», это не «копирование» коммита, а «повторение» того, что вы сделали из одной ветви в текущую, над которой вы работаете.Вы также можете сказать, что git cherry pick - это: «git автоматически копирует и вставляет все, что вы написали из этой другой ветки в этом коммите, а затем git фиксирует это в текущей ветке для вас».Следовательно, дата является текущей датой , и также не имеет смысла перемещать новый коммит назад :).

Это не совсем так, потому что он говорит вам, что какой-то человек совершил новый код, и что этот код был скопирован из другой ветки.И это было сделано сегодня.:)

0 голосов
/ 20 сентября 2018

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

Как комментаторыукажите:

  • Это прекрасно, если вы работаете локально, и
  • У объекта фиксации фактически есть две даты.

Если вы заботитесьтолько в том, что порядок фиксации «имеет смысл», вы также можете изменить дату выбранного коммита, используя rebase --committer-date-is-author-date, сводя к минимуму потенциальные проблемы, поскольку вы, вероятно, еще не выдвинули этот конкретный коммит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...