1.7 cherry-pick, revert, rebase
El libro se puede descargar aquí
Ya han visto como son los merge conflicts, los que aparecen cuando se
hace una operación de mezcla. Hay otras 3 operaciones que pueden generar
conflictos:
Aunque la mecánica básica es la misma, cada sección del CB tiene un significado
diferente
1.7.1 cherry-pick - Ejemplo 12
En git 2.27, se introdujo este cambio:
Listing 1.115:Ejemplo 12 - Cambio de 3be7efcafceeae34$ git show --pretty= 3be7efcafceeae34 diff --git a/commit-graph.c b/commit-graph.c index f013a84e29..e4f1a5b2f1 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -23,6 +23,7 @@ #define GRAPH_CHUNKID_DATA 0x43444154 /* "CDAT" */ #define GRAPH_CHUNKID_EXTRAEDGES 0x45444745 /* "EDGE" */ #define GRAPH_CHUNKID_BASE 0x42415345 /* "BASE" */ +#define MAX_NUM_CHUNKS 5 #define GRAPH_DATA_WIDTH (the_hash_algo->rawsz + 16) @@ -1350,8 +1351,8 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) int fd; struct hashfile *f; struct lock_file lk = LOCK_INIT; - uint32_t chunk_ids[6]; - uint64_t chunk_offsets[6]; + uint32_t chunk_ids[MAX_NUM_CHUNKS + 1]; + uint64_t chunk_offsets[MAX_NUM_CHUNKS + 1]; const unsigned hashsz = the_hash_algo->rawsz; struct strbuf progress_title = STRBUF_INIT; int num_chunks = 3;
Podemos ver la forma en la que se cambia la forma en la que se define el tamaño
de chunk_ids y chunk_offsets a usar una macro.
Como un experimento, queremos hacer un backport de este cambio sobre
v2.22.4.
Listing 1.116:ejemplo 12 - haciendo backport de 3be7efcafceeae34$ git checkout v2.22.4 HEAD is now at c9808fa014 Git 2.22.4 $ git cherry-pick 3be7efcafceeae34 Auto-merging commit-graph.c CONFLICT (content): Merge conflict in commit-graph.c error: could not apply 3be7efcafc... commit-graph: define and use MAX_NUM_CHUNKS hint: after resolving the conflicts, mark the corrected paths hint: with ’git add <paths>’ or ’git rm <paths>’ hint: and commit the result with ’git commit’ $ git status HEAD detached at v2.22.4 You are currently cherry-picking commit 3be7efcafc. (fix conflicts and run "git cherry-pick --continue") (use "git cherry-pick --skip" to skip this patch) (use "git cherry-pick --abort" to cancel the cherry-pick operation) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: commit-graph.c no changes added to commit (use "git add" and/or "git commit -a")
Como se ve este conflicto? Hay 2 CBs en commit-graph.c. El primero de ellos
se ve así:
CB#1
Listing 1.117:Ejemplo 12 - CB#1 en commit-graph.c25<<<<<<< HEAD 26||||||| parent of 3be7efcafc... commit-graph: define and use MAX_NUM_CHUNKS 27#define GRAPH_CHUNKID_BASE 0x42415345 /* "BASE" */ 28======= 29#define GRAPH_CHUNKID_BASE 0x42415345 /* "BASE" */ 30#define MAX_NUM_CHUNKS 5 31>>>>>>> 3be7efcafc... commit-graph: define and use MAX_NUM_CHUNKS
Se ve muy parecido a los conflictos que hemos visto hasta ahora, cierto?
Exactamente como en un merge, hay 3 secciones en el CB y seguiremos usando los
mismos términos/acrónimos que hemos usado. El primero es el UB, en otras
palabras, el código como está en HEAD. En este caso, la etiqueta v2.22.4, dado
que ahí es donde estamos trabajando. A diferencia de un merge, donde
se ve el código de el ancestro común en el MB y de la otra rama
en el LB, durante una operación de cherry-pick, los otros dos bloques
muestran otra cosa, como indican las marcas de conflicto. El MB nos muestra el
contenido de el papá de la revisión a la que le estamos haciendo cherry-pick
. El
LB nos muestra el código como está en la revisión 3be7efcafc, que es la que
estamos tratando de hacerle cherry-pick. Aunque el MB y el LB se refieren a
conceptos diferentes a los de un merge, la forma de hacer análisis es la misma que
hemos utilizado.
dMU#1
La macro GRAPH_CHUNKID_BASE (presente en la línea 27) fue
borrado.
dML#1
La macro MAX_NUM_CHUNKS fue agregada en la línea 30.
Resolución#1
No veo mucha diferencia entre trabajar desde el UB o el LB.... simplemente es un
poco más sencillo borrar que tener que copiar cambios de un sitio al otro por lo
tanto trabajaremos desde el LB:
Listing 1.118:Ejemplo 12 - LB#1 en commit-graph.c28======= 29#define GRAPH_CHUNKID_BASE 0x42415345 /* "BASE" */ 30#define MAX_NUM_CHUNKS 5 31>>>>>>> 3be7efcafc... commit-graph: define and use MAX_NUM_CHUNKS
Luego, como lo pide el dMU, borramos GRAPH_CHUNKID_BASE.
Listing 1.119:Ejemplo 12 - LB#1 en commit-graph.c28======= 29#define MAX_NUM_CHUNKS 5 30>>>>>>> 3be7efcafc... commit-graph: define and use MAX_NUM_CHUNKS
Se remueven las otras secciones del conflicto y los marcadores y terminamos.
Listing 1.120:Ejemplo 12 - Solución del CB#1 en commit-graph.c24#define GRAPH_CHUNKID_EXTRAEDGES 0x45444745 /* "EDGE" */ 25#define MAX_NUM_CHUNKS 5 26 27#define GRAPH_DATA_WIDTH (the_hash_algo->rawsz + 16)
Luego vamos al CB#2 en commit-graph.c:
CB#2
Listing 1.121:Ejemplo 12 - CB#2 en commit-graph.c1031<<<<<<< HEAD 1032 uint32_t chunk_ids[5]; 1033 uint64_t chunk_offsets[5]; 1034||||||| parent of 3be7efcafc... commit-graph: define and use MAX_NUM_CHUNKS 1035 uint32_t chunk_ids[6]; 1036 uint64_t chunk_offsets[6]; 1037======= 1038 uint32_t chunk_ids[MAX_NUM_CHUNKS + 1]; 1039 uint64_t chunk_offsets[MAX_NUM_CHUNKS + 1]; 1040>>>>>>> 3be7efcafc... commit-graph: define and use MAX_NUM_CHUNKS
dMU#2
El tamaño de chunk_ids y chunk_offsets fue cambiado de 6 a 5.
dML#2
Descartamos el valor numérico y los reemplazamos por MAX_NUM_CHUNKS
+ 1, usando la macro dedinida en el CB anterior.
Resolución#2
En este caso especial, podemos quedarnos con lo que tenemos en el LB “tal cual“
dado que el cambio de 6 a 5 no tiene incidencia en el requerimiento: Seguimos usando
la macro así que:
Listing 1.122:Ejemplo 12 - Solución del CB#2 en commit-graph.c1030 struct lock_file lk = LOCK_INIT; 1031 uint32_t chunk_ids[MAX_NUM_CHUNKS + 1]; 1032 uint64_t chunk_offsets[MAX_NUM_CHUNKS + 1]; 1033 const unsigned hashsz = the_hash_algo->rawsz;
Y listo!
... O bueno, eso creen! Recuerdan la intención de la revisión a la que le estamos
haciendo cherry-pick? Se refería a la forma en la que se define el tamaño de
los arreglos para que usen una macro. Eso es probablemente para poder
fácilmente cambiar su tamaño luego de ser necesario con solo ajustar el
valor de la macro. Bien! Pero no la estamos aplicando en una revisión que
tenía 6 como tamaño del arreglo. El tamaño del arreglo en HEAD
es 5 y ese tamaño debe permanecer igual. Lo que significa que debemos
cambiar el tamaño del macro a 4, para que el tamaño de los arreglos sea
el correcto. Así que debemos regresar al CB#1 y ajustar el valor de la
macro:
Listing 1.123:Ejemplo 12 - Ajuste de la solución del CB#1 en commit-graph.c24#define GRAPH_CHUNKID_EXTRAEDGES 0x45444745 /* "EDGE" */ 25#define MAX_NUM_CHUNKS 4 26 27#define GRAPH_DATA_WIDTH (the_hash_algo->rawsz + 16)
Y ahora sí terminamos! Esa es la forma en la que el dMU entra en juego
en la resolución del conflicto, aunque no fue en el CB que estábamos
trabajando.
Pregunta: estaría bien si dejamos la macro con el valor de 5 y cambiamos los
arreglos en el CB#2 para que usen MAX_NUMS_CHUNKS? De esta
forma:
Listing 1.124:Ejemplo 12 - Solución alternativa al CB#2 en commit-graph.c1030 struct lock_file lk = LOCK_INIT; 1031 uint32_t chunk_ids[MAX_NUM_CHUNKS]; 1032 uint64_t chunk_offsets[MAX_NUM_CHUNKS]; 1033 const unsigned hashsz = the_hash_algo->rawsz;
Desde el punto de vista del código, podría estarlo
. El
código compila y se comporta de la forma esperada, cierto? Pero están rompiendo
la intención de la revisión a la que le están haciendo cherry-pick. Solo para
que se imaginen un posible escenario como consecuencia de esto, que sucedería si,
más adelante, necesitaran hacer un cherry-pick de otra revisión que use el valor
de esta misma macro? Ahora que el valor ha sido roto, tendrán que introducir más
ajustes sobre el código por sobre la intención de lo que estén haciéndole
cherry-pick en ese momento.... y puede ser que ni si quiera tengan conflictos
cuando hagan el cherry-pick. Se podrán acordar de este cambio para que
logren detectar estas situaciones para arreglar el código? Yo se que sí
podría.... pero solo por los siguientes 30 segundos luego de modificar el
código, pero no creo que lo pueda recordar más allá de eso.... y se qué es
extremadamente difícil que todos logremos recordar todos estos detalles.
Conclusión: Apéguense a la intención original del parche. Considérense
advertidos.
1.7.2 revert - Ejemplo 13
Cuando se quiere revertir cambios que fueron introducidos por una revisión, la operación que se
aplica es revert .
Consideremos un pequeño ejemplo de git:
Desde el repo de git, hagan checkout de la etiqueta v2.26.2. Vamos a revertir la
revisión 22a69fda197f. Primero veamos lo que hizo la revisión originalmente
sobre builtin/rebase.c:
Listing 1.125:Ejemplo 13 - Revisión original$ git show --pretty="" 22a69fda197f -- builtin/rebase.c diff --git a/builtin/rebase.c b/builtin/rebase.c index 8081741f8a..faa4e0d406 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -453,8 +453,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix) OPT_NEGBIT(0, "ff", &opts.flags, N_("allow fast-forward"), REBASE_FORCE), OPT_BOOL(0, "keep-empty", &opts.keep_empty, N_("keep empty commits")), - OPT_BOOL(0, "allow-empty-message", &opts.allow_empty_message, - N_("allow commits with empty messages")), + OPT_BOOL_F(0, "allow-empty-message", &opts.allow_empty_message, + N_("allow commits with empty messages"), + PARSE_OPT_HIDDEN), OPT_BOOL(0, "rebase-merges", &opts.rebase_merges, N_("rebase merge commits")), OPT_BOOL(0, "rebase-cousins", &opts.rebase_cousins, N_("keep original branch points of cousins")), @@ -1495,9 +1496,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) OPT_STRING_LIST(’x’, "exec", &exec, N_("exec"), N_("add exec lines after each commit of the " "editable list")), - OPT_BOOL(0, "allow-empty-message", - &options.allow_empty_message, - N_("allow rebasing commits with empty messages")), + OPT_BOOL_F(0, "allow-empty-message", + &options.allow_empty_message, + N_("allow rebasing commits with empty messages"), + PARSE_OPT_HIDDEN), {OPTION_STRING, ’r’, "rebase-merges", &rebase_merges, N_("mode"), N_("try to rebase merges instead of skipping them"),
La revisión cambió las llamadas originales a OPT_BOOL por OPT_BOOL_F
para definir allow-empty-message, y se hizo unos ajustes sobre los parámetros de
las llamadas. Eso quiere decir que debemos terminar con una llamada a
OPT_BOOL para definir allow-empty-message si queremos revertir, cierto?
Intentémoslo:
Listing 1.126:Ejemplo 13 - Revirtiendo$ git revert --no-commit 22a69fda197f Auto-merging builtin/rebase.c CONFLICT (content): Merge conflict in builtin/rebase.c Auto-merging Documentation/git-rebase.txt error: could not revert 22a69fda19... git-rebase.txt: update description of --allow-empty-message hint: after resolving the conflicts, mark the corrected paths hint: with ’git add <paths>’ or ’git rm <paths>’ $ git status HEAD detached at v2.26.2 You are currently reverting commit 22a69fda19. (fix conflicts and run "git revert --continue") (use "git revert --skip" to skip this patch) (use "git revert --abort" to cancel the revert operation) Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: Documentation/git-rebase.txt Unmerged paths: (use "git restore --staged <file>..." to unstage) (use "git add <file>..." to mark resolution) both modified: builtin/rebase.c
Hay un CB en builtin/rebase.c:
Listing 1.127:Ejemplo 13 - CB en builtin/rebase.c473<<<<<<< HEAD 474 { OPTION_CALLBACK, ’k’, "keep-empty", &options, NULL, 475 N_("(DEPRECATED) keep empty commits"), 476 PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, 477 parse_opt_keep_empty }, 478 OPT_BOOL_F(0, "allow-empty-message", &opts.allow_empty_message, 479 N_("allow commits with empty messages"), 480 PARSE_OPT_HIDDEN), 481||||||| 22a69fda19... git-rebase.txt: update description of --allow-empty-message 482 OPT_BOOL(0, "keep-empty", &opts.keep_empty, N_("keep empty commits")), 483 OPT_BOOL_F(0, "allow-empty-message", &opts.allow_empty_message, 484 N_("allow commits with empty messages"), 485 PARSE_OPT_HIDDEN), 486======= 487 OPT_BOOL(0, "keep-empty", &opts.keep_empty, N_("keep empty commits")), 488 OPT_BOOL(0, "allow-empty-message", &opts.allow_empty_message, 489 N_("allow commits with empty messages")), 490>>>>>>> parent of 22a69fda19... git-rebase.txt: update description of --allow-empty-message
Esto no es muy diferente de lo que vimos anteriormente en cherry-pick, cierto?
UB es como está el código en v2.26.2, dado que esa es la revisión donde
estábamos al comenzar. La parte interesante es en los otros dos bloques. Se pueder
ver por los marcadores que es MB es como se ve el código en la revisión que
queremos revertir (en otras palabras, el código luego de aplicar la revisión
originalmente) y en UB está como se ve en el padre de la revisión que queremos
revertir, es decir el orden opuesto de cómo se presentam estos dos bloques a
cuando se hace un cherry-pick. En cherry-pick, el MB es el paá de la revisión a
la que se le hace cherry-pick y en LB está el código luego de aplicar la revisión.
Eso significa que, justo como en merge y cherry-pick, nosotros debemos seguir la
misma metodología que hemos aplicado hasta ahora analizando el dMU y el
dML.
dMU
La forma en la que se define keep-empty se cambia de una llamada a
OPT_BOOL() en la línea 482 a una definición a mano en las líneas
474-477.
dML
La forma en la que se define allow-empty-message se cambia de una llamada a
OPT_BOOL_F() en las líneas 483-485 a una llamada a OPT_BOOL() en las
líneas 488-489, lo cual también remueve PARSE_OPT_HIDDEN como
parámetro de la llamada.
Resolución
Nos quedaremos trabajando en el UB, solo porque el cambio de la definición de
keep-empty es más grande que el cambio de la definición de allow-empty-message.
Luego aplicaremos el cambio de la llamada de la macro OPT_BOOL_F() a
OPT_BOOL() (líneas 478-480):
Listing 1.128:Ejemplo 13 - Paso 1 UB en builtin/rebase.c473<<<<<<< HEAD 474 { OPTION_CALLBACK, ’k’, "keep-empty", &options, NULL, 475 N_("(DEPRECATED) keep empty commits"), 476 PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, 477 parse_opt_keep_empty }, 478 OPT_BOOL_F(0, "allow-empty-message", &opts.allow_empty_message, 479 N_("allow commits with empty messages"), 480 PARSE_OPT_HIDDEN), 481||||||| 22a69fda19... git-rebase.txt: update description of --allow-empty-message
Removemos PARSE_OPT_HIDDEN como parámetro (presente en la línea
480):
Listing 1.129:Ejemplo 13 - Paso 2 UB en builtin/rebase.c473<<<<<<< HEAD 474 { OPTION_CALLBACK, ’k’, "keep-empty", &options, NULL, 475 N_("(DEPRECATED) keep empty commits"), 476 PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, 477 parse_opt_keep_empty }, 478 OPT_BOOL(0, "allow-empty-message", &opts.allow_empty_message, 479 N_("allow commits with empty messages")), 480||||||| 22a69fda19... git-rebase.txt: update description of --allow-empty-message
Desplazamos la segunda línea de los argmentos para que esté alineada con la
posición de la llamada (línea 479):
Listing 1.130:Ejemplo 13 - Paso 3 UB en builtin/rebase.c473<<<<<<< HEAD 474 { OPTION_CALLBACK, ’k’, "keep-empty", &options, NULL, 475 N_("(DEPRECATED) keep empty commits"), 476 PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, 477 parse_opt_keep_empty }, 478 OPT_BOOL(0, "allow-empty-message", &opts.allow_empty_message, 479 N_("allow commits with empty messages")), 480||||||| 22a69fda19... git-rebase.txt: update description of --allow-empty-message
Y ya terminamos con el revert:
Listing 1.131:Ejemplo 13 - Solución del CB en builtin/rebase.c470 struct option options[] = { 471 OPT_NEGBIT(0, "ff", &opts.flags, N_("allow fast-forward"), 472 REBASE_FORCE), 473 { OPTION_CALLBACK, ’k’, "keep-empty", &options, NULL, 474 N_("(DEPRECATED) keep empty commits"), 475 PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, 476 parse_opt_keep_empty }, 477 OPT_BOOL(0, "allow-empty-message", &opts.allow_empty_message, 478 N_("allow commits with empty messages"), 479 OPT_BOOL(0, "rebase-merges", &opts.rebase_merges, N_("rebase merge commits")),
Y podemos ver como terminamos con la llamada a OPT_BOOL() para definir
allow-empty-message, justo lo que queríamos para lograr la reversión.
Sólo para que vean que las mismas reglas aplican para hacer el revert,
intenten hacer la resolución del conflicto pero trabajando desde el LB y
aplicando los cambios del dMU. Deben terminar con exactamente el mismo
código.
1.7.3 rebase - Ejemplo 14
Juguemos un poco. Del repo de git, hagan checkout de la revisión ce9baf234f.
Veamos una sección del código de builtin/push.c en esta revisión:
Listing 1.132:Ejemplo 14 - Sección de builtin/push.c en ce9baf234f548 OPT_BIT(’f’, "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE), 549 { OPTION_CALLBACK, 550 0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"), 551 N_("require old value of ref to be at this value"), 552 PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parseopt_push_cas_option }, 553 OPT_CALLBACK(0, "recurse-submodules", &recurse_submodules, "(check|on-demand|no)", 554 N_("control recursive pushing of submodules"), option_parse_recurse_submodules), 555 OPT_BOOL_F( 0 , "thin", &thin, N_("use thin pack"), PARSE_OPT_NOCOMPLETE),
Miren cuidadosamente la forma en la que <refname>:<expect> y
recurse-submodules están definidas. <refname>:<expect> se define
manualmente en las líneas 549-552 y recurse-submodules se define con una
llamada a OPT_CALLBACK en las líneas 553-554.
Pidámosle a git que haga un rebase sobre la revisión
6652716200 .
Deben ver un CB relativo a la ección de builtin/push.c que les mostré
previamente:
Listing 1.133:Ejemplo 14 - CB en builtin/push.c550 OPT_BIT(’f’, "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE), 551<<<<<<< HEAD 552 OPT_CALLBACK_F(0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"), 553 N_("require old value of ref to be at this value"), 554 PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parseopt_push_cas_option), 555 { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, "(check|on-demand|no)", 556 N_("control recursive pushing of submodules"), 557 PARSE_OPT_OPTARG, option_parse_recurse_submodules }, 558||||||| parent of ce9baf234f... push: unset PARSE_OPT_OPTARG for --recurse-submodules 559 { OPTION_CALLBACK, 560 0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"), 561 N_("require old value of ref to be at this value"), 562 PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parseopt_push_cas_option }, 563 { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, "(check|on-demand|no)", 564 N_("control recursive pushing of submodules"), 565 PARSE_OPT_OPTARG, option_parse_recurse_submodules }, 566======= 567 { OPTION_CALLBACK, 568 0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"), 569 N_("require old value of ref to be at this value"), 570 PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parseopt_push_cas_option }, 571 OPT_CALLBACK(0, "recurse-submodules", &recurse_submodules, "(check|on-demand|no)", 572 N_("control recursive pushing of submodules"), option_parse_recurse_submodules), 573>>>>>>> ce9baf234f... push: unset PARSE_OPT_OPTARG for --recurse-submodules 574 OPT_BOOL_F( 0 , "thin", &thin, N_("use thin pack"), PARSE_OPT_NOCOMPLETE),
Recuerdan la revisión en la que estábamos cuando corrimos el rebase? Era la
ce9baf234f, cierto? Miren el UB. Se ve como lo que está en ce9baf234f? No? Ok.
Y el LB? Ah, ahí está! Y entonces qué hay en el UB? Recuerdan que les dije
que en UB siempre está lo que hay en HEAD? Pues bien, eso pasa también
en este caso. El truco es darse cuenta de que cuando se hace un rebase,
primero git tiene que hacer checkout de la rama sobre la que se va a a hacer
el rebase y entonces se aplican las revisiones a las que se les va a hacer
rebase.
Así que, en nuestro ejemplo, en UB se vería el código como está en
6652716200 y en LB se vería el códogo como lo que está en ce9baf234f. En
MB se vería el papá de la revisión que se está tratando de aplicar en ese
momento. En todo caso, siempre se puede ver los detalles de lo que hay en cada
sección del CB a través de las marcas de conflicto.
Ahora que hemos aclarado todo el asunto, es el momento de continuar con nuestro
análisis como lo hemos hecho hasta ahora, sin cambios:
dMU
La forma en la que se define<refname>:<expect> es cambiada de a mano en las
líneas 559-562 por una llamada a OPT_CALLBACK_F() en las líneas
552-554.
dML
La forma en la que se define recurse-submodules se cambia de a mano en las
líneas 563-565 a una llamada a OPT_CALLBACK() en las líneas
571-572.
Resolución
No veo mucha diferencia entre trabajar desde el UB o desde el LB. Comencemos a
trabajar desde el UB:
Listing 1.134:Ejemplo 14 - Paso 1 UB en builtin/push.c550<<<<<<< HEAD 551 OPT_CALLBACK_F(0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"), 552 N_("require old value of ref to be at this value"), 553 PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parseopt_push_cas_option), 554 { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, "(check|on-demand|no)", 555 N_("control recursive pushing of submodules"), 556 PARSE_OPT_OPTARG, option_parse_recurse_submodules }, 557||||||| parent of ce9baf234f... push: unset PARSE_OPT_OPTARG for --recurse-submodules
Modificamos la forma en la que se define recurse-submodules según el dML:
Listing 1.135:Ejemplo 14 - Paso 2 UB en builtin/push.c550<<<<<<< HEAD 551 OPT_CALLBACK_F(0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"), 552 N_("require old value of ref to be at this value"), 553 PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parseopt_push_cas_option), 554 OPT_CALLBACK(0, "recurse-submodules", &recurse_submodules, "(check|on-demand|no)", 555 N_("control recursive pushing of submodules"), option_parse_recurse_submodules), 556||||||| parent of ce9baf234f... push: unset PARSE_OPT_OPTARG for --recurse-submodules
Y listo!
Listing 1.136:Ejemplo 14 - Solución del CB en builtin/push.c550 OPT_BIT(’f’, "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE), 551 OPT_CALLBACK_F(0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"), 552 N_("require old value of ref to be at this value"), 553 PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parseopt_push_cas_option), 554 OPT_CALLBACK(0, "recurse-submodules", &recurse_submodules, "(check|on-demand|no)", 555 N_("control recursive pushing of submodules"), option_parse_recurse_submodules), 556 OPT_BOOL_F( 0 , "thin", &thin, N_("use thin pack"), PARSE_OPT_NOCOMPLETE),
Agregamos el archivo al índice, no hay nada más pendiente y podemos continuar con
el rebase. .
1.7.4 Tips
Regarless of the operation being done (merge, cherry-pick, revert, rebase), always use
the same technique to solve conflicts: dMU/dML, Resolution.
Copyright 2020 Edmundo Carmona Antoranz