не удалось создать фиксацию: текущий совет не является первой родительской ошибкой во время фиксации в libgit2

Я использую библиотеку libgit2 v0.23.0 для операции git pull & commit. Я вызываю метод git_merge(repo,their_heads,1,&merge_opt,&checkout_opts);, и он отлично работает и объединяет изменения из удаленного репозитория в локальный репозиторий. Но после этого, когда я вызываю метод git_commit_create(), он выдает ошибку не удалось создать фиксацию: текущий совет не является первым родителем с кодом ошибки -15.

Я исследовал и обнаружил, что файлы FETCH_HEAD и MERGE_HEAD содержат обновленный oid, но ORIG_HEAD по-прежнему содержит предыдущий/устаревший oid. Я не уверен, что это причина ошибки, которую я получаю во время git_commit_create().

int fetch()
{
qDebug()<<"Fetch";
git_remote *remote = NULL;
const git_transfer_progress *stats;
struct dl_data data;
git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
git_repository *repo = NULL;
QString repoPath = "repopath/.git";
int  error = git_repository_open(&repo, repoPath.toStdString().c_str());

if (git_remote_lookup(&remote, repo, "origin") < 0) {
    if (git_remote_create_anonymous(&remote, repo,"repoURL") < 0)
        return -1;
}
fetch_opts.callbacks.update_tips = &update_cb;
fetch_opts.callbacks.sideband_progress = &progress_cb;
fetch_opts.callbacks.credentials = cred_acquire_cb;


data.remote = remote;
data.fetch_opts = &fetch_opts;
data.ret = 0;
data.finished = 0;

stats = git_remote_stats(remote);


download(&data);

if (stats->local_objects > 0) {
    printf("\rReceived %d/%d objects in % bytes (used %d local objects)\n",
           stats->indexed_objects, stats->total_objects, stats->received_bytes, stats->local_objects);
} else{
    printf("\rReceived %d/%d objects in %bytes\n",
           stats->indexed_objects, stats->total_objects, stats->received_bytes);
}
git_remote_disconnect(remote);

if (git_remote_update_tips(remote, &fetch_opts.callbacks, 1, fetch_opts.download_tags, NULL) < 0)
    return -1;

const git_remote_head **head = NULL;
size_t size = 0;
(git_remote_ls(&head, &size, remote));
git_oid oid = head[0]->oid;
char * commit_id1 = new char[41]; //Commit ID
qDebug()<<"oid:"<<git_oid_tostr(commit_id1, 41, &oid);
git_annotated_commit  *anno_out  ;
git_annotated_commit_lookup(&anno_out,repo,&oid);
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
const git_annotated_commit **their_heads = const_cast<const git_annotated_commit**>(&anno_out);
git_merge_options merge_opt = GIT_MERGE_OPTIONS_INIT;
merge_opt.file_favor = GIT_MERGE_FILE_FAVOR_UNION;

error =  git_merge(repo,their_heads,1,&merge_opt,&checkout_opts);
if(error!=0){

   //Error handling
}
else{
    qDebug()<<"Merge successfully";
}

git_repository_state_cleanup(repo);
/* Create signature */
git_signature *me = NULL;
(git_signature_now(&me, "username", "[email protected]"));

//Tree Lookup
git_tree *tree;
git_object *tree_obj;
(git_revparse_single(&tree_obj, repo, "HEAD^{tree}"));

// Get parent commit
git_oid parentCommitId;
git_commit *parent;
git_oid remoteParentCommitId;
git_commit *remoteParent;
int nparents;
int err;
(git_reference_name_to_id( &parentCommitId, repo, "ORIG_HEAD" ));
(git_commit_lookup( &parent, repo, &parentCommitId ));
(git_reference_name_to_id( &remoteParentCommitId, repo, "MERGE_HEAD" ));
(git_commit_lookup( &remoteParent, repo, &remoteParentCommitId ));

const git_commit *parents [1] = {remoteParent };

git_oid new_commit_id;
err = (git_commit_create(
           &new_commit_id,
           repo,
           "HEAD",                      /* name of ref to update */
           me,                          /* author */
           me,                          /* committer */
           "UTF-8",                     /* message encoding */
           "pull fetch",            /* message */
           (git_tree *) tree_obj,                        /* root tree */
           1,                    /* parent count */
           parents));                    /* parents */


if(err !=0){
//I am getting error here
}

git_remote_free(remote);

return 0;

}

Пожалуйста, подскажите, что мне нужно сделать, чтобы решить эту проблему?


person Monty    schedule 05.12.2015    source источник
comment
Как вы звоните git_commit_create?   -  person Edward Thomson    schedule 05.12.2015
comment
@EdwardThomson: я отредактировал свой вопрос и добавил дополнительную информацию. Не могли бы вы проверить это один раз?   -  person Monty    schedule 07.12.2015
comment
Пожалуйста, не ставьте псевдотеги «нравится [решено]» в заголовке вашего вопроса. Сайт уже поддерживает концепцию решенных вопросов, позволяя вам выбрать принятый ответ.   -  person meagar    schedule 25.12.2015


Ответы (1)


Как правило, вы видите эту ошибку, потому что вы создаете новую фиксацию в ветке, родительский элемент которой не является текущей вершиной ветки. Действительно, вы создаете новый коммит, чьим родителем является удаленный коммит, а не локальный.

Есть несколько проблем:

  1. Рекомендуется проверка некоторых ошибок для всех функций. Я вижу некоторые функции, которые, вероятно, не работают, но это не проверяется. Например:

  2. Не звоните git_repository_state_cleanup посреди операции. Это прервет слияние и очистит файлы состояния, которые вы пытаетесь прочитать позже. Как 2_.

  3. Вы делаете слияние. У вас должно быть два родительских коммита (два коммита, которые вы объединяете) для нового коммита. Вы должны передать { parent, remoteParent } в качестве родителей.

person Edward Thomson    schedule 07.12.2015
comment
Я выполнил вышеуказанные шаги, и теперь он работает нормально. Спасибо. Но он отображается как master|MERGING всякий раз, когда я открываю репозиторий в GIT bash. В чем причина этого? - person Monty; 08.12.2015
comment
Как только вы закончите слияние, самое время очистить состояние, чтобы больше не сливать. - person Edward Thomson; 08.12.2015