From a19dcb3108440806361cab4f81fb42f66971ca8e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 6 Aug 2026 07:17:17 +0800 Subject: [PATCH] vim-patch:9.2.0914: diff: undo after :diffget into an empty buffer leaves a line behind (#41181) Problem: After :diffget into an empty buffer, undo does not restore the empty buffer, the last line stays behind (Narendran Gopalakrishnan) Solution: Include the empty line of the empty buffer in the undo information, it is deleted once the first line was obtained (Hirohito Higashi). fixes: vim/vim#20950 closes: vim/vim#20951 https://github.com/vim/vim/commit/c44f35ca1a4d8c0c78f327800fe2677c91c6cecb Co-authored-by: Hirohito Higashi Co-authored-by: Claude Opus 5 (1M context) --- src/nvim/diff.c | 5 ++++- test/old/testdir/test_diffmode.vim | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/nvim/diff.c b/src/nvim/diff.c index cb1576971d..bc69314f4f 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -3822,9 +3822,12 @@ static void diffgetput(const int addr_count, const int idx_cur, const int idx_fr bool did_free = false; linenr_T lnum = dp->df_lnum[idx_to]; linenr_T count = dp->df_count[idx_to]; + // The empty line of an empty buffer is deleted below, include it in + // the undo information, otherwise undo leaves a line behind. + linenr_T undo_bot = lnum + count + (count == 0 && buf_is_empty(curbuf) ? 1 : 0); if ((dp->df_lnum[idx_cur] + dp->df_count[idx_cur] > line1 + off) - && (u_save(lnum - 1, lnum + count) != FAIL)) { + && (u_save(lnum - 1, undo_bot) != FAIL)) { // Inside the specified range and saving for undo worked. linenr_T start_skip = 0; linenr_T end_skip = 0; diff --git a/test/old/testdir/test_diffmode.vim b/test/old/testdir/test_diffmode.vim index b5e2c886ba..2733ffc36b 100644 --- a/test/old/testdir/test_diffmode.vim +++ b/test/old/testdir/test_diffmode.vim @@ -253,6 +253,24 @@ func Test_diffget_diffput() %bwipe! endfunc +" Undo after getting lines into an empty buffer must leave it empty again +func Test_diffget_undo_empty_buffer() + enew! + diffthis + new + call setline(1, ['1', '2']) + diffthis + + wincmd p + normal do + call assert_equal(['1', '2'], getline(1, '$')) + undo + call assert_equal([''], getline(1, '$')) + + windo diffoff + %bwipe! +endfunc + " Test putting two changes from one buffer to another func Test_diffput_two() new a