Retool discard operation during conflict

The use of --theirs for Unstaged and --ours for Staged was based
entirely on the way conflicts were represented in git status --short,
except, that's backwards, the staged column contains our side of the
merge so discarding it should use --theirs.  I never noticed because I
don't use this feature.

Fixing this is guaranteed to burn anybody who learned the whole
behavior, so let's promote 2X and 3X to official status, and require
opting in to the flipped default.

Also, since --ours and --theirs only touch the worktree, the correct
analogous operations for deletion is *not* git rm, but rather to remove
the worktree file directly.  So let's do that, and add it to 2X and 3X
too.

Closes https://github.com/tpope/vim-fugitive/issues/1699

References https://github.com/tpope/vim-fugitive/issues/1648
This commit is contained in:
Tim Pope
2021-03-16 16:04:17 -04:00
parent cc525c99df
commit caf2907fd8
2 changed files with 27 additions and 9 deletions

View File

@@ -3614,6 +3614,7 @@ endfunction
function! s:StageDelete(lnum1, lnum2, count) abort
let restore = []
let err = ''
let did_conflict_err = 0
try
for info in s:Selection(a:lnum1, a:lnum2)
if empty(info.paths)
@@ -3646,14 +3647,30 @@ function! s:StageDelete(lnum1, lnum2, count) abort
elseif info.status ==# '?'
call s:TreeChomp('clean', '-f', '--', info.paths[0])
elseif a:count == 2
call s:TreeChomp('checkout', '--ours', '--', info.paths[0])
if get(b:fugitive_files['Staged'], info.filename, {'status': ''}).status ==# 'D'
call delete(FugitiveVimPath(info.paths[0]))
else
call s:TreeChomp('checkout', '--ours', '--', info.paths[0])
endif
elseif a:count == 3
call s:TreeChomp('checkout', '--theirs', '--', info.paths[0])
if get(b:fugitive_files['Unstaged'], info.filename, {'status': ''}).status ==# 'D'
call delete(FugitiveVimPath(info.paths[0]))
else
call s:TreeChomp('checkout', '--theirs', '--', info.paths[0])
endif
elseif info.status =~# '[ADU]' &&
\ get(b:fugitive_files[info.section ==# 'Staged' ? 'Unstaged' : 'Staged'], info.filename, {'status': ''}).status =~# '[AU]'
call s:TreeChomp('checkout', info.section ==# 'Staged' ? '--ours' : '--theirs', '--', info.paths[0])
if get(g:, 'fugitive_conflict_x', 0)
call s:TreeChomp('checkout', info.section ==# 'Unstaged' ? '--ours' : '--theirs', '--', info.paths[0])
else
if !did_conflict_err
let err .= '|echoerr "Use 2X for --ours or 3X for --theirs"'
let did_conflict_err = 1
endif
continue
endif
elseif info.status ==# 'U'
call s:TreeChomp('rm', '--', info.paths[0])
call delete(FugitiveVimPath(info.paths[0]))
elseif info.status ==# 'A'
call s:TreeChomp('rm', '-f', '--', info.paths[0])
elseif info.section ==# 'Unstaged'
@@ -3661,7 +3678,9 @@ function! s:StageDelete(lnum1, lnum2, count) abort
else
call s:TreeChomp('checkout', 'HEAD^{}', '--', info.paths[0])
endif
call add(restore, ':Gsplit ' . s:fnameescape(info.relative[0]) . '|' . undo)
if len(undo)
call add(restore, ':Gsplit ' . s:fnameescape(info.relative[0]) . '|' . undo)
endif
endfor
catch /^fugitive:/
let err .= '|echoerr ' . string(v:exception)

View File

@@ -255,10 +255,9 @@ U Unstage everything.
X Discard the change under the cursor. This uses
`checkout` or `clean` under the hood. A command is
echoed that shows how to undo the change. Consult
`:messages` to see it again. You can use this during
a merge conflict to discard "our" changes (--theirs)
in the "Unstaged" section or discard "their" changes
(--ours) in the "Staged" section.
`:messages` to see it again. During a merge conflict,
use 2X to call `checkout --ours` or 3X to call
`checkout --theirs` .
*fugitive_=*
= Toggle an inline diff of the file under the cursor.