Как зафиксировать репозиторий git с помощью libgit2?

Поскольку нет примера копирования-вставки для создания коммита без использования файлов на диске с libgit2 насколько я могу судить я думал, что должен добавить один.

Не забывайте, что в настоящее время (март 2013 г.) libgit2 находится в полной разработке, поэтому ознакомьтесь с официальной документацией и исходным кодом, так как новые функции добавляются ежедневно:


person Nicu Tofan    schedule 29.03.2013    source источник
comment
Хотя это не аккуратный код (я рефакторинг), я сделал именно это. Я вставляю файлы, которые хочу зафиксировать, прямо в индекс и фиксирую их без записи на диск. См. репозиторий Gitorium.   -  person T0xicCode    schedule 01.04.2013
comment
Выдает мне ошибку 404. Это частный репозиторий?   -  person Nicu Tofan    schedule 02.04.2013
comment
Название организации изменилось, а URL-адрес был обновлен. Это правильный URL.   -  person T0xicCode    schedule 08.04.2013


Ответы (1)


bool addGitCommit ( 
  git_repository * repo, git_signature * sign, 
  const char * content, int content_sz,
  const char * message )
{
  int rc;              /* return code for git_ functions */
  git_oid oid_blob;    /* the SHA1 for our blob in the tree */
  git_oid oid_tree;    /* the SHA1 for our tree in the commit */
  git_oid oid_commit;  /* the SHA1 for our initial commit */
  git_blob * blob;     /* our blob in the tree */
  git_tree * tree_cmt; /* our tree in the commit */
  git_treebuilder * tree_bld;  /* tree builder */
  bool b = false;

  /* create a blob from our buffer */
  rc = git_blob_create_frombuffer( 
        &oid_blob,
        repo, 
        content, 
        content_sz );
  if ( rc == 0 ) { /* blob created */
    rc = git_blob_lookup( &blob, repo, &oid_blob );
    if ( rc == 0 ) { /* blob created and found */
      rc = git_treebuilder_create( &tree_bld, NULL );
      if ( rc == 0 ) { /* a new tree builder created */
        rc = git_treebuilder_insert( 
              NULL, 
              tree_bld, 
              "name-of-the-file.txt", 
              &oid_blob, 
              GIT_FILEMODE_BLOB );
        if ( rc == 0 ) { /* blob inserted in tree */
          rc = git_treebuilder_write( 
                &oid_tree, 
                repo, 
                tree_bld );
          if ( rc == 0 ) { /* the tree was written to the database */
            rc = git_tree_lookup(
                  &tree_cmt, repo, &oid_tree );
            if ( rc == 0 ) { /*we've got the tree pointer */  
              rc = git_commit_create(
                    &oid_commit, repo, "HEAD",
                    sign, sign, /* same author and commiter */
                    NULL, /* default UTF-8 encoding */
                    message,
                    tree_cmt, 0, NULL );
              if ( rc == 0 ) {
                b = true;
              }
              git_tree_free( tree_cmt );
            }
          }
        }
        git_treebuilder_free( tree_bld );
      }
      git_blob_free( blob );
    }
  }
  return b;
}

Репозиторий происходит от git_repository_init() или git_repository_open(). Подпись происходит от git_signature_now() или git_signature_new().

Функция обновляет HEAD для текущей ветки.

Если вы сделаете git status после выполнения функции, вы заметите, что файл name-of-the-file.txt отображается как удаленный. Это потому, что функция не создает фактический файл, а только запись в базе данных git.

Также обратите внимание на последние аргументы git_commit_create(). 0 и NULL означают, что это первая (корневая) фиксация. Для всех остальных должен быть указан хотя бы родительский коммит, возможно, полученный с помощью git_commit_lookup().


Я только учусь этим вещам. Пожалуйста, улучшите этот ответ, если вы знаете лучше.

person Nicu Tofan    schedule 29.03.2013
comment
Что-то похожее< /b> также существует в LibGit2Sharp (привязки .Net). - person nulltoken; 30.03.2013
comment
Также были проведены некоторые обсуждения относительно добавления функции, которая облегчила бы создание коммитов без участия индекса или рабочего каталога. Он должен появиться в сообщении libgit2 v1.0. - person nulltoken; 30.03.2013
comment
Спасибо. Я обновил вопрос, чтобы ссылки были более заметны, чем внизу ответа. - person Nicu Tofan; 30.03.2013
comment
Итак, после того как вы создадите фиксацию, нужно ли предпринять какие-либо оставшиеся шаги? Например, нужно ли мне записывать эту фиксацию на диск? Обновить индекс до нового индекса? Обновить HEAD и/или текущую ветку, чтобы указать на эту фиксацию и т. д.? (Потому что сейчас это, похоже, ничего не делает..) - person NHDaly; 13.04.2013
comment
Кроме того, -- извините --, я немного запутался: какой контент передается в фиксацию, которая помещается в наш большой двоичный объект? Разве содержимое коммита не должно быть просто состоянием текущего индекса? Спасибо за разъяснения! - person NHDaly; 13.04.2013
comment
Содержимое представляет собой массив символов. Любой контент, скажем const char * data = "abcsef"; Этот конкретный контент связан с name-of-the-file.txt и после этого, поскольку файл не появляется на диске, с точки зрения git он удаляется. - person Nicu Tofan; 13.04.2013
comment
Взгляните на libgit2.github.com/libgit2/#HEAD/group/ коммит/git_commit_create; HEAD в нашем случае обновляется, чтобы указать на этот коммит: const char * update_ref If not NULL, name of the reference that will be updated to point to this commit. If the reference is not direct, it will be resolved to a direct reference. Use "HEAD" to update the HEAD of the current branch and make it point to this commit. If the reference doesn't exist yet, it will be created. - person Nicu Tofan; 13.04.2013
comment
Обратите внимание, что стиль в этом коде ужасен. Идея состоит в том, чтобы проверять rc для каждого вызова и обрабатывать ошибку, этот код очень затрудняет отслеживание того, что происходит. - person Iharob Al Asimi; 20.06.2016
comment
@iharob Хотите сделать версию pastebin / gist, которая, по вашему мнению, является более явной / подходящей / соответствующей основным стилям? Затем я мог бы заменить размещенный код. - person Nicu Tofan; 20.06.2016
comment
@TNick Ты можешь это исправить! Просто используйте goto вместо множества вложенных if. Подумайте, какой из них хуже? Хороший goto, который явно ведет вас к очищающей (повторяемой) части функции или запутанным вложенным if, которые так трудно понять. - person Iharob Al Asimi; 21.06.2016
comment
@iharob Я, наверное, мог бы, конечно, может быть, даже используя шаблон for(;;) { if (...) break; }; прошло много времени с тех пор, как я опубликовал это, и с тех пор я многому научился; но я приглашал ВАС перейти на следующий уровень: не только указать на недостаток, но и исправить его. Что вы скажете на этот вызов? :) - person Nicu Tofan; 21.06.2016
comment
@TNick, это не вызов, и я буду рад, я действительно хочу. Но сейчас у меня нет времени. Я буду. - person Iharob Al Asimi; 21.06.2016