tpope / vim-fugitive

fugitive.vim: A Git wrapper so awesome, it should be illegal
https://www.vim.org/scripts/script.php?script_id=2975
20.03k stars 1.01k forks source link

Possibility of comparing 2 hashes on view only mode #2338

Closed rugobal closed 1 month ago

rugobal commented 1 month ago

I'm using 'Telescope git_bcommits'. Is it possible to compare two different hashes of the same file? Something like:

:Gvdiffsplit hash1 hash2

How to achieve this? If not, could it be added?

Thanks

tpope commented 1 month ago

If I understand you correctly, I think you want something like :Gvdiffsplit hash1:%|Gvdiffsplit hash2:%.

rugobal commented 1 month ago

I tried and didn't work as expected. I managed to write a function in Lua though:

      local function git_diff_selected_commits(prompt_bufnr)
        local picker = action_state.get_current_picker(prompt_bufnr)
        local multi_selection = picker:get_multi_selection()

        if #multi_selection ~= 2 then
          print("Please select exactly two commits to compare")
          return
        end

        actions.close(prompt_bufnr)

        local sha1 = multi_selection[1].value
        local sha2 = multi_selection[2].value

        -- Get commit dates
        local date_format = '%Y%m%d%H%M%S'
        local date_cmd = 'git show -s --format=%cd --date=format:' .. date_format .. ' '

        local date1_output = vim.fn.systemlist(date_cmd .. sha1)
        local date2_output = vim.fn.systemlist(date_cmd .. sha2)

        local date1 = tonumber(date1_output[1])
        local date2 = tonumber(date2_output[1])

        if date1 == nil or date2 == nil then
          print("Unable to retrieve commit dates")
          return
        end

        -- Determine which commit is older
        local sha_left, sha_right
        if date1 <= date2 then
          -- sha1 is older
          sha_left = sha2     -- newer commit
          sha_right = sha1    -- older commit
        else
          -- sha2 is older
          sha_left = sha1     -- newer commit
          sha_right = sha2    -- older commit
        end

        -- Get the file path relative to the repository root
        local file = vim.fn.expand('%')
        local repo_path = vim.fn.systemlist('git rev-parse --show-toplevel')[1]:gsub('%s+', '')
        local rel_file_path = Path:new(file):make_relative(repo_path)

        -- Open the newer commit (left pane) in the current window
        vim.cmd('Gedit ' .. sha_left .. ':' .. rel_file_path)
        local winid_left = vim.api.nvim_get_current_win()

        -- Open a vertical split to the right
        vim.cmd('vsplit')

        -- In the new window (right pane), open the older commit
        vim.cmd('Gedit ' .. sha_right .. ':' .. rel_file_path)
        local winid_right = vim.api.nvim_get_current_win()

        -- Start diff mode between the two windows
        vim.cmd('diffthis')
        vim.api.nvim_set_current_win(winid_left)
        vim.cmd('diffthis')
mappings = {
...
  ["<C-o>"] = git_diff_selected_commits,
...
}

It works by selecting 2 commits with Tab in Telescope git_bcommits and then pressing Ctrl+o

Just in case anyone is interested