| Age | Commit message (Collapse) | Author | Files | Lines |
|
The sequencer machinery (used by 'git rebase', 'git cherry-pick', and
'git revert') has been updated to defer automatic maintenance tasks
until the end of the operation, preventing nested 'git commit', 'git
merge', and 'exec' commands from triggering GC operations that could
contend for locks or delete open packs while the sequence is in
progress.
* tb/rerere-lock-grace:
sequencer: disable auto maintenance in spawned commands
rebase, cherry-pick, revert: run auto maintenance when done
config: add git_config_append_parameter()
|
|
A commit that is emptied by melding a 'fixup!' or 'squash!' commit
during 'git rebase --autosquash' is now handled according to the
'--empty' option, allowing it to be dropped, kept, or to halt the
rebase.
* fz/rebase-autosquash-empty:
sequencer: honor --empty when a fixup!/squash! empties its target
|
|
The experimental 'git history' command has been taught a new 'squash'
subcommand to fold a range of commits into a single commit, with any
descendants replayed on top.
* hn/history-squash:
history: support editing squashed commit messages
history: create squashed commits without editing
history: protect branches when squashing a range
history: validate squash revision ranges
history: add skeleton for squash subcommand
sequencer: share the squash message marker helpers and flags
history: give commit_tree_ext a message template
history: extract helper for a commit's parent tree
|
|
Support for skipping the editor when continuing a rebase after
conflict resolution has been added with the '--no-edit' option, and
forcing it with '--edit'. A new configuration variable
'rebase.noEdit' can be used to set the default behavior.
* hs/rebase-continue-edit:
rebase: add --[no-]edit to --continue
|
|
'git rebase --update-refs' has been taught to resolve local branch
symrefs to their referents before queuing updates, ensuring aliases of
the current branch are skipped and duplicate updates are avoided to
prevent failures when branch aliases are present.
* sn/rebase-update-refs-symrefs:
rebase: guard non-branch symref targets
rebase: skip branch symref aliases
|
|
The mechanism to register in-memory alternate object sources has
been removed, as submodule object databases are now accessed
natively via their own repository structures. This simplifies
object database management and prepares the codebase for migrating
alternate tracking into the files backend.
* ps/odb-stop-registering-in-memory-sources:
odb: remove the ability to link sources ad-hoc
t/helper: stop registering alternates in "ref-store" command
t/helper: adapt read-midx to not link ad-hoc source anymore
builtin/multi-pack-index: refuse unknown sources with "--object-dir="
odb/packed: fix memory leaks when freeing source
tmp-objdir: drop unused function to register alternate
odb: remove infrastructure to register submodule sources
builtin/grep: stop registering submodule ODB as source
submodule-config: stop registering submodule sources
submodule-config: stop using `the_hash_algo`
submodule-config: remove uses of `the_repository`
cache-tree: remove dependency on `the_repository`
cache-tree: drop `the_repository` in `cache_tree_fully_valid()`
|
|
The autostash fallback in 'git checkout -m' has been refined to only
retry when there are local changes. Additionally, a blank line now
visually separates autostash conflict advice from the subsequent
branch-switch message.
* hn/checkout-m-autostash-refine:
checkout: separate autostash conflict advice from branch-switch message
stash: reserve exit status 1 for conflicts
|
|
Teach 'am', 'revert', and 'rebase' that running 'commit --amend' or a
partial 'commit <paths>' makes no sense during operations that stop
and return control to the user to resolve conflicts left in the
working tree, just like 'cherry-pick' and 'merge' do.
* en/no-amend-during-conflicts:
commit: refuse partial commits during conflict resolution
commit: refuse to amend during conflict resolution
commit: reword the empty-commit rebase amend error
commit: allow a partial commit when a rebase pick becomes empty
commit: clarify FROM_REBASE_PICK and is_from_rebase() names
|
|
Sequencer-spawned commands like 'commit' and 'merge' run
background auto maintenance, which interferes with ongoing
operations (e.g. 'rerere gc' holding MERGE_RR.lock or repacks
deleting active packs).
Pass maintenance.auto=false via GIT_CONFIG_PARAMETERS to the
spawned commit, merge and exec commands. Appending it after the
user's own settings ensures it wins, and the environment reaches
whatever they spawn in turn.
Auto maintenance now runs exactly once when the sequence
completes. Commands run manually by the user while stopped are
unaffected and continue to run auto maintenance normally.
Assisted-by: Claude Fable 5.1
Signed-off-by: Thomas Bachem <mail@thomasbachem.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
When "git rebase -i" squashes commits it builds an editor template with a
"This is a combination of N commits." banner, a "This is the 1st/Nth
commit message:" header above each kept message (or a "will be skipped"
header for a dropped one), and a commented-out subject for any fixup!,
squash! or amend! commit. The banner, the headers and the
subject-commenting all live in static helpers in sequencer.c wired to the
rebase state, so no other command can present a squash the same way.
Pull the three pieces out into add_squash_combination_header(),
add_squash_message_header() (which takes a flag for the "will be skipped"
variant) and squash_subject_comment_len(), and use them from
update_squash_messages() and append_squash_message(). Also move the
todo_item_flags enum to the header, so a caller reading the output of
todo_list_rearrange_squash() can tell an amend! (TODO_REPLACE_FIXUP_MSG)
from a plain fixup!. A later change reuses all of this to give "git
history squash" the same template.
No change in behavior.
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
"git stash apply", "pop" and "branch" exit with status 1 both when
applying the stash entry resulted in conflicts and when they fail for
other reasons, so callers cannot tell the two apart.
Follow the convention of "git merge-tree" and the merge strategies,
which exit with status 1 to indicate conflicts and with a different
non-zero status for errors: those subcommands now exit with status 1
only when applying the stash entry resulted in conflicts, in which
case the stash entry is left in place, and exit with status 128, the
status die() uses, when they fail for other reasons. Document the
exit statuses.
The only subcommand implementations that can return a positive value
are "apply", "pop" and "branch", which return the value of
do_apply_stash(): "apply" returns it directly, and "pop" and "branch"
drop the stash entry, via do_drop_stash(), which always returns 0,
only when the application succeeded. do_apply_stash() only returns a
positive value when the three-way merge was unclean. cmd_stash() now
maps negative values to 128 and passes positive values through as the
exit status, so exit status 1 unambiguously indicates conflicts.
enum stash_apply_result makes the convention explicit, and the
autostash helpers use it to tell users that their stashed changes
were saved when applying them fails.
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The function `cache_tree_fully_valid()` verifies whether the cache tree
owned by the index is valid or not. As part of that, the function checks
whether the objects referenced by the cache all exist. But because the
function has no repository available, it is using the object database of
`the_repository` instead.
We could of course adapt callers to pass in a repository as parameter
explicitly to get rid of this implicit dependency on global state. But
all of them pass the cache tree owned by a `struct index_state`, and
that structure already has a reference to its owning repository.
So instead, adapt the function to accept a `struct index_state`, which
ensures that callers will implicitly always pass the correct repository.
Adapt callers accordingly.
Suggested-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Running `git commit --amend` during conflict resolution is an ugly
foot-gun. For many years, we have rejected amending during conflict
resolution in the middle of
- a merge
- a cherry-pick
However, this was never extended to other operations that can also
produce conflicts:
- an `am` operation
- a revert
- a rebase
Extend it to handle these other cases now.
Extending to `am`, revert, and the apply backend of rebase are fairly
straightforward. However, with the merge backend of rebase we have to
be more careful, since it powers interactive rebases and
- the interactive machinery internally uses `git commit --amend` for
`squash` and `reword` directives
- users are expected to `git commit --amend` after hitting an `edit`
or `break` directive
So, we need to be careful with rebase to only reject amending when doing
conflict resolution.
A few files under the rebase-merge/ directory provide us the necessary
information:
- stopped-sha is written only when the rebase stops and hands control
back to the user, so its presence marks a genuine stop -- as opposed
to the sequencer's own internal `git commit --amend` while applying
a squash, fixup, or reword, during which no stopped-sha exists.
- amend is written only when the rebase stops with HEAD already
pointing at the commit the user is meant to amend: a clean `edit`,
or a fast-forward `reword`. Its absence at a stop therefore means
the commit did not apply, so HEAD is the previously-applied commit
rather than the one being rebased -- exactly the case we refuse.
So for the merge backend we die when stopped-sha exists and amend does
not. This covers a plain conflicted pick as well as a conflicted `edit`
(both leave HEAD on the previously-applied commit), while still allowing
a clean `edit` or `reword` stop and a `break` stop (no stopped-sha).
stopped-sha is unlinked at the start of the resume loop, so a resumed
squash's internal amend is unaffected.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Commit 430b75f7209c (commit: give correct advice for empty commit during
a rebase, 2019-12-06) introduced a FROM_REBASE_PICK enum value and an
is_from_rebase() function. Those names failed to convey that they were
specifically about hitting a commit that becomes empty when rebasing.
Clarify their names now.
While at it, change `whence == FROM_REBASE_NOW_EMPTY` to use
`is_from_rebase_now_empty(whence)`.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
When "git rebase --autosquash" squashes a "fixup!" or "squash!" commit
into its target, the result can be a commit that no longer changes
anything relative to its parent, for example when the squashed change
reverts the target. Rather than dropping or keeping that commit, the
rebase stops with
You asked to amend the most recent commit, but doing so would
make it empty. ...
and "--empty" has no effect on it. This makes backing a change out of a
series awkward: reverting a commit as a "fixup!" and running "git rebase
--autosquash --empty=drop" ought to remove both the commit and its
revert, but it halts instead.
A "fixup" is applied by amending HEAD, so the commit it produces is
empty when the index matches the tree of HEAD's parent rather than the
tree of HEAD. allow_empty() only knows about the latter, so it never
notices that the fixup cancelled the commit out and "git commit --amend"
is left to refuse to create the empty commit.
Check for this case separately and honor "--empty" for it, subject to
two restrictions.
First, "--empty" only governs commits that become empty, so a commit
that was picked empty to begin with must be left alone. To tell the two
apart, record in "struct replay_ctx" what the "pick" that created the
commit at HEAD was, and write it to "$GIT_DIR/rebase-merge/fixup-target"
so that it survives a stop for conflict resolution. Only a commit
created by a "pick" is a candidate: when the todo list has been edited
so that a chain starts after "reset", "exec" or "break", we do not know
how the commit at HEAD came to be and keep it.
Second, only the last fixup of a chain may drop the commit. Were an
earlier one to drop it, the fixups still to come would be squashed into
the previous commit instead, so a commit emptied mid-chain is kept --
empty for the time being -- and the decision is deferred to the end of
the chain.
With "--empty=drop" the emptied commit has already been created by the
"pick", so drop it by moving HEAD back to its parent and report the new
PICK_RESULT_DROPPED_HEAD, so that neither that commit nor any of the
fixups squashed into it is recorded as rewritten and the post-rewrite
machinery has nothing to report. A "label" or "update-ref" that follows
then sees HEAD at the parent.
A conflicted fixup that the user resolves by undoing the commit it is
being squashed into leaves the same empty commit behind, so give
commit_staged_changes() the same treatment.
Signed-off-by: Farid Zakaria <farid.m.zakaria@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The setting of a now-unused member '.pretty_given' in the sequencer
machinery has been removed.
* en/sequencer-lose-pretty-given:
sequencer: remove unnecessary variable setting
|
|
As of 4557f1add261 (rebase--helper: add a builtin helper for interactive
rebases, 2017-02-09), continuing an interactive rebase uses the builtin
sequencer, which spawns `git commit`.
The child may trigger auto-maintenance, which may need to replace files
for which the sequencer still holds resources. See
https://github.com/git-for-windows/git/issues/6315: on Windows, this
produces unlink retry prompts that cannot succeed while the sequencer
waits for the child.
Resources such as file handles or memory mappings must be released
before spawning a command that may run auto-maintenance, as established
by 28d04e1ec197 (run-command: offer to close the object store before
running, 2021-09-09): release the ODB file handles and memory mappings,
so that auto-gc can repack (potentially deleting existing packfiles in
the process); If the sequencer needs to access the ODB afterwards, it
will gracefully (re-)open the ODB.
Release the sequencer's ODB before spawning `git commit`. The regression
test uses the legacy-delete trick introduced by 69ed0e35a754 (mingw:
optionally use legacy (non-POSIX) delete semantics, 2026-05-07) to
trigger the failure on modern Windows.
Assisted-by: GPT-5.6 Sol
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
revs.pretty_given is only ever read in builtin/log.c, and nothing from
builtin/log.c is ever called from sequencer.c. So setting this variable
cannot do anything.
This was introduced in commit 62db524779 ("rebase -i: generate the
script via rebase--helper", 2017-07-14), which used `git rev-list` even
though its commit message describes the logic as having been based on
`git log`. Because of this, I am guessing this line was copied or
ported from part of builtin/log.c without recognizing that this line was
not doing anything and could be removed.
It's certainly not doing anything now, though, so remove it.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Two bugs in how 'git rebase' handles skipped 'fixup' and 'squash'
commands have been fixed. One bug caused an incorrect commit count to
be shown in the template message when multiple commands were skipped,
and another prevented the editor from opening when the final command
in a chain containing 'fixup -c' was skipped.
* pw/rebase-fixup-fixes:
rebase: remember fixup -c after skipping fixup/squash
rebase -i: fix counting of fixups after rebase --skip
|
|
The rebase post-rewrite notes-copying logic has been corrected. When
a commit is dropped during rebase (e.g., because its changes are
already upstream), it is no longer recorded as rewritten, preventing
its notes from being copied to an unrelated commit.
* pw/rebase-drop-notes-with-commit:
sequencer: do not record dropped commits as rewritten
sequencer: use an enum to represent result of picking a commit
sequencer: simplify pick_one_commit()
sequencer: remove unnecessary condition in pick_one_commit()
sequencer: simplify handling of fixup with conflicts
sequencer: remove unnecessary "or" in pick_one_commit()
sequencer: never reschedule on failed commit
sequencer: be more careful with external merge
t3400: restore coverage for note copying with apply backend
|
|
When the final command in a chain of "fixup" and "squash" commands
is skipped, we should prompt the user to edit the commit message
if the chain contains a "fixup -c" command that was not skipped.
Unfortunately, commit_staged_changes() only looks for completed "squash"
commands and so does not prompt the user to edit the message. Fix
this by recording whether a fixup command has the "-c" flag set and
then checking whether we have seen either a "fixup -c" or a "squash"
command. Add regression tests for skipping a command in the middle
of the chain (which currently works but has no test coverage), and
for skipping the final command (which is fixed by this patch).
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
When the sequencer processes a chain of "fixup" and "squash" commands
it keeps a list of the commands that have been executed. If there are
conflicts, then the list is saved when the rebase stops for the user to
resolve them. When the rebase resumes, the list is loaded and is used
to initialize the count of how many "fixup" and "squash" commands have
been processed; if a command has been skipped with "git rebase --skip",
then the last command needs to be popped off the end of the list.
To count the number of commands, commit_staged_changes() uses the
number of newlines in the file plus one. This is due to the slightly
unusual way the list is constructed - instead of appending a newline
when a command is added, a newline is inserted before the command
if the current count is greater than zero. Therefore, when we pop a
skipped command off the list, we should also remove the newline that
precedes it. Otherwise, when a new command is added, a blank line
will be left before it, which will contribute to the fixup count the
next time the file is read. Unfortunately, the preceding newline is
not removed, leading to an incorrect count. Fix this by removing the
newline that appears before the skipped command.
In addition to fixing the code that removes a skipped command from the
list, the code that reads the list is fixed to skip blank lines. We
have had reports of users starting a rebase with one version of
git and continuing it with another. Often this happens because the
version of git bundled with an IDE or TUI differs from the one used
at the command line. By fixing both the reading and writing ends of
the problem we ensure the count is correct when an older version of
git reads the fixup file written by a newer version and vice versa.
Triggering the incorrect count requires the user to skip two "fixup" or
"squash" commands before the final command in the chain. An existing
test is extended to prevent future regressions. The consequence of
miscounting is not serious: we just print the wrong count in the
header of the commit message template.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
A local branch symbolic ref may point outside refs/heads/. Such an alias
cannot be skipped like a branch-to-branch alias because its concrete
target ref is absent from the local branch decoration list.
However, queuing each alias independently can update the same target ref
more than once and make the second compare-and-swap fail. A reservation
from another worktree can also name either an alias or its resolved
target ref, so checking only one form can miss an in-progress update.
Fix these cases by checking both the literal alias and its resolved
target ref against checked-out reservations. Deduplicate updates by
target ref. Also reserve both forms when loading another worktree's
update-refs state. This makes different aliases honor the same
in-progress update.
This keeps non-branch symrefs supported without allowing duplicate or
cross-worktree ref updates.
Signed-off-by: Son Luong Ngoc <sluongng@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
git rebase --update-refs can finish rewriting the current branch and
then fail while updating a local branch that is a symbolic ref. This can
happen during a default-branch rename where refs/heads/main points at
refs/heads/master while users migrate.
The problem is a partially applied ref update: the main rebase has
already succeeded when the later ref update fails.
The sequencer queues updates from local branch decorations. Commit
106b6885c7 (rebase: ignore non-branch update-refs) filters out
decorations such as HEAD and tags. A branch symref is still a local
branch decoration, but refs_update_ref() dereferences it, so an alias to
another branch duplicates the concrete branch update.
Resolve local branch decorations before queuing them. Skip symrefs whose
targets are under refs/heads/ so that only the concrete branch update is
queued. Keep an owned copy of the resolved HEAD and skip the current
branch before checked-out handling so later ref resolution cannot change
the comparison.
This prevents a successful rebase from being followed by a failed,
partially applied ref update while preserving each alias as a symref.
Signed-off-by: Son Luong Ngoc <sluongng@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Allow skipping the editor when continuing after resolving conflicts,
via --no-edit or the rebase.noEdit configuration variable. The --edit
option overrides rebase.noEdit when both are set.
Signed-off-by: Hugo Sales <hugo@hsal.es>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
When copying a file we need to potentially adapt permissions of the new
file based on whether or not "core.shared" is enabled. Parsing this
configuration makes us implicitly depend on `the_repository`.
Refactor the code to instead require the caller to pass in a repository
so that we can remove `USE_THE_REPOSITORY_VARIABLE`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The experimental 'git history' command has been taught a new 'drop'
subcommand to remove a commit, with its descendants replayed onto its
parent.
* ps/history-drop:
builtin/history: implement "drop" subcommand
builtin/history: split handling of ref updates into two phases
replay: expose `replay_result_queue_update()`
reset: stop assuming that the caller passes in a clean index
reset: allow the caller to specify the current HEAD object
reset: introduce ability to skip updating HEAD
reset: introduce dry-run mode
reset: modernize flags passed to `reset_working_tree()`
reset: rename `reset_head()`
reset: drop `USE_THE_REPOSITORY_VARIABLE`
read-cache: split out function to drop unmerged entries to stage 0
|
|
If a commit gets dropped because its changes are already upstream
then we should not record it as rewritten. As well as confusing any
post-rewrite hooks, it means we end up copying the notes from the
dropped commit to the commit that was picked immediately before the
one that was dropped.
While we do not want to record the dropped commit as rewritten, if
it is the final commit in a chain of fixups then we need to flush
the list of rewritten commits. The behavior of an "edit" command
where the commit is dropped is changed so that "rebase --continue"
will not amend the previous pick. However, as the code comment notes
it will still be erroneously recorded as rewritten when the rebase
continues. That will need to be addressed separately along with not
recording skipped commits as rewritten.
The initialization of "drop_commit" is moved to ensure it is initialized
when rewording a fast-forwarded commit.
Reported-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Tested-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Rather than using an integer where -1 is an error, 0 is success and 1
indicates there were conflicts, use an enum. This is clearer and lets
us add a separate return value for commits that are dropped because
they become empty in the next commit.
Note we continue to use "return error(...)" to return errors and
take advantage of C's lax typing of enums
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Unless we're rebasing, all we do in pick_one_commit() is call
do_pick_commit() and return its result. Simplify the code by returning
early if we're not rebasing so that we don't have to repeatedly call
is_rebase_i() in the rest of the function. Note that there are a couple
of conditions that do not call is_rebase_i() but they check for either
an "edit" or a "fixup" command, both of which imply we're rebasing.
The only block that does not return early is the one guarded by
"!res". Move the return into that block to make it clear that after
recording the commit as rewritten, all we do is return from the
function.
As the conditional blocks are all mutually exclusive (either the
conditions are mutually exclusive, or an earlier conditional block
that would match a later one contains a "return" statement) chain
them together with "else if" to make that clear.
While we could remove "res" from the conditions below "if (!res)"
they are left alone because, when we start using an enum in the next
commit, it makes it clear that these clauses are handling cases where
there are conflicts.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
item->commit holds the commit to be picked and so it must be non-NULL
otherwise pick_one_commit() would not know which commit to pick.
It is also unconditionally dereferenced in do_pick_commit() which is
called at the top of this function. Therefore the check to see if it
is non-NULL is superfluous.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Commit e032abd5a0 (rebase: fix rewritten list for failed pick,
2023-09-06) introduced an early return when res == -1, so if
we enter this conditional block then res is positive. After the
last couple of commits the only possible positive value is 1. That
means we can simplify the code by removing the conditional call to
intend_to_amend() and have error_failed_squash() request that it is
called in error_with_patch() instead.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
If error_with_patch(..., res, ...) succeeds then it returns "res", if
it fails then it returns -1. This means that or-ing the return value
with "res" is pointless as the result is the same as the return value.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
If "git commit" fails to run then run_git_commit() returns -1 which
causes the current command to be rescheduled. This is incorrect as
we have successfully picked the commit and have written all the state
files we need to successfully commit when the user continues. Fix this
by converting -1 to 1 which matches what do_merge() does.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
If an external merge strategy cannot merge (for example because it
would overwrite an untracked file) it exits with a non-zero exit
code other than 1. This should be treated differently from a merge
with conflicts, which is signaled by an exit code of 1, because, as
the merge failed, we need to reschedule the last pick. The caller
expects us to return -1 in this case. Also reschedule without trying
to merge if the commit message cannot be written as that prevents us
from successfully picking the commit.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The display of the rebase todo list in "git status" has been
improved to correctly abbreviate object IDs for more commands and
avoid misinterpreting refs as object IDs.
* pw/status-rebase-todo:
status: improve rebase todo list parsing
sequencer: factor out parsing of todo commands
|
|
In a subsequent commit we'll introduce a new caller to
`reset_working_tree()` that really only wants to update the index and
working tree, without updating any references. Introduce a new flag that
makes the caller opt in to updating HEAD and adapt all callers to set
that flag.
Note that in a previous iteration we instead introduced a flag that made
callers opt out of updating any references. This was somewhat awkward
though because we already have the `UPDATE_ORIG_HEAD` flag, so the
result was somewhat inconsistent.
Suggested-by: Phillip Wood <phillip.wood123@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
[jc: fixed-up a typo pointed out by Christian]
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The flags passed to `reset_working_tree()` are declared as defines. This
has fallen a bit out of practice nowadays, where we instead prefer to
use enums. Furthermore, the prefix of those flags does not match the
function name anymore after the rename in the preceding commit.
Adapt the code to follow modern best practices and adapt the flag names.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
In a subsequent commit we're about to adapt `reset_head()` so that the
reference update to HEAD is optional, only. At this point the function
starts to feel misnamed, as it doesn't necessarily have anything to do
with the HEAD reference anymore. The gist of the function then is that
we reset the working tree to a specific new commit, updating both the
index and the checked-out files.
Rename it to `reset_working_tree()` to better reflect that.
Note that we don't adjust the flags yet. This will happen in a
subsequent commit.
Suggested-by: Phillip Wood <phillip.wood123@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Move the code that parses todo commands into a separate function so
that it can be shared with "git status" in the next commit. As we
know the input is NUL terminated we do not pass a pointer to the end
of the line and instead test for a blank line by looking for NUL, CR
LF, or LF. We use starts_with() instead of starts_with_mem() for the
same reason. This results in slightly different behavior when there
a CR at the start of the line that is not followed by LF. Previously
such a line was treated as a comment rather than an invalid line.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Formatting object name in full hexadecimal form has been optimized
by using a new strbuf_add_oid_hex() helper function.
* rs/strbuf-add-oid-hex:
hex: add and use strbuf_add_oid_hex()
|
|
Code clean-up.
* ag/sequencer-remove-unused-struct-member:
sequencer: remove todo_add_branch_context.commit
|
|
"git rebase --update-refs", when used with an rebase.instructionFormat
with "%d" (describe) in it, tried to update local branch HEAD by
mistake, which has been corrected.
* ag/rebase-update-refs-limit-to-branches:
rebase: ignore non-branch update-refs
|
|
Add a function for adding the full hexadecimal hash value of an object
ID to a strbuf. It's thread-safe and slightly more efficient than using
strbuf_addstr() with oid_to_hex() because it doesn't have to determine
the length of the string or copy it from the intermediate static buffer.
Add and apply a semantic patch to use it throughout the code base.
I get a tiny speedup for git log showing a single hash per commit:
Benchmark 1: ./git_main log --format=%H
Time (mean ± σ): 91.2 ms ± 0.7 ms [User: 51.9 ms, System: 38.6 ms]
Range (min … max): 89.8 ms … 92.6 ms 31 runs
Benchmark 2: ./git log --format=%H
Time (mean ± σ): 90.5 ms ± 0.7 ms [User: 51.0 ms, System: 38.8 ms]
Range (min … max): 89.2 ms … 92.3 ms 32 runs
Summary
./git log --format=%H ran
1.01 ± 0.01 times faster than ./git_main log --format=%H
Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The 'commit' field in 'struct todo_add_branch_context' is unused.
It's written to, but never read from.
add_decorations_to_list() gets the commit passed to it explicitly
as an argument.
Signed-off-by: Abhinav Gupta <mail@abhinavg.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The following Git configuration breaks git rebase --update-refs:
[rebase]
instructionFormat = %s%d
The '%d' format requests all available decorations for a commit,
filling the global decoration table with all of them,
which --update-refs then uses to populate 'update-ref' instructions
in the rebase todo list.
Specifically, this results in the following instruction:
update-ref HEAD
The todo parser then rejects the instruction:
error: update-ref requires a fully qualified refname e.g. refs/heads/HEAD
error: invalid line 3: update-ref HEAD
To fix, ignore decorations that are not local branches
when scanning through the table.
This matches the documented contract:
it moves branch refs under refs/heads/
and leaves display-only decorations (HEAD, tags, etc.) alone.
Verification:
A regression test that fails without this fix is included.
Signed-off-by: Abhinav Gupta <mail@abhinavg.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
When switching branches with "git checkout -m", the attempted merge
of local modifications may cause conflicts with the changes made on
the other branch, which the user may not want to (or may not be able
to) resolve right now. Because there is no easy way to recover from
this situation, we discouraged users from using "checkout -m" unless
they are certain their changes are trivial and within their ability
to resolve conflicts.
Teach the -m flow to create a temporary stash before switching and
reapply it after. On success, the stash is silently applied and
the list of locally modified paths is shown, same as a successful
"git checkout" without "-m".
If reapplying causes conflicts, the stash is kept and the user is
told they can resolve and run "git stash drop", or run "git reset
--hard" and later "git stash pop" to recover their changes.
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Add label_ours, label_theirs, label_base, and stash_msg parameters to
apply_autostash_ref() and the autostash apply machinery so callers can
pass custom conflict marker labels through to
"git stash apply --label-ours/--label-theirs/--label-base", as well as
a custom stash message for "git stash store -m".
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Add a silent parameter to create_autostash_internal and introduce
create_autostash_ref_silent so that callers can create an autostash
without printing the "Created autostash" message.
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
"git replay" (experimental) learns, in addition to "pick" and
"replay", a new operating mode "revert".
* sa/replay-revert:
replay: add --revert mode to reverse commit changes
sequencer: extract revert message formatting into shared function
|