Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to display version history from a Git repository, in addition to File Recovery and Obsidian Sync? #3

Closed
00dani opened this issue Mar 14, 2022 · 14 comments

Comments

@00dani
Copy link

00dani commented Mar 14, 2022

As you mention in the README.md, the diffs produced from the File Recovery snapshots are often more helpful than the diffs produced from Obsidian Sync versions since they're less frequent. The same is true of Git commits to a larger extent, since a Git commit is only produced when the user intentionally makes one - the revision history is deliberately curated and annotated with descriptive messages, rather than automatically generated at set intervals.

Hence it'd be really nice to see diffs and history produced by asking Git how the active file has changed! This oddly enough isn't a feature of the existing Obsidian Git plugin, despite being a common operation that you can perform using Git integration in various text editors and IDEs.

I don't know how well it'll work on mobile, nor whether you'd need to rely on Obsidian Git being present, but it'd still be a really nice feature to have on desktop. 🐱

@kometenstaub
Copy link
Owner

kometenstaub commented Mar 14, 2022

List changed files: Lists all changes in a modal

The obsidian git plugin has an option to list all changes, but I've never looked at what exactly it does.

I suppose it doesn't work with the active file, but commits in general.

Anything I could do would need to work with the obsidian git plugin alone, because any reliance on node would stop the plugin from working on mobile. It doesn't work properly on mobile right now because of CSS issues, but that's something that can be fixed.

I feel that the obsidian git plugin is the right place to implement it. It already has everything it needs to work with git and could build on its own Diff view (which uses the same library for generating the html).

@kometenstaub
Copy link
Owner

cc @Vinzent03

@Vinzent03
Copy link

@kometenstaub Thanks for the mention

@00dani There is already a diff view. Just open the Source Control View via the command palette and double-click an unstaged file.

@00dani
Copy link
Author

00dani commented Mar 14, 2022

Hmm, Obsidian Git does have a diff view, akin to git diff somefile.md, which shows you any unstaged changes to the selected file since the last commit.

However what this plugin does is different! It's actually closer to git log somefile.md, showing you the history of prior versions for the selected file and allowing you to examine the changes made in each of those versions. It's like asking Fugitive to :0Gclog, or asking IntelliJ to Show History.

It's also kinda like git blame, but because Obsidian uses word-wrapping and variable fonts by default, decorating each line with commit annotations is less helpful than it is in text editors and IDEs. 🤷‍♀️

@kometenstaub
Copy link
Owner

What I need is an API that gets me all commit hashes for the chosen file, plus info like commit time. Then I can pass them to another api and let it return the diff.

Getting just diffs isn't useful, because they only diff the former commit, but with my UI the user can choose the commits.

If these APIs are made available by the git plugin, then I could add git compatibility. Before that, I'd need to do more refactoring though.

@Vinzent03
Copy link

@00dani Ah interesting. I didn't know this plugin before.

@kometenstaub So you pass the file path to my method, and it returns you a list of all commits hashes with their commit time? How do you get the diff from the commit hash? You would need node modules, don't you?

@kometenstaub
Copy link
Owner

kometenstaub commented Mar 14, 2022

How you get the diff

this.plugin.gitManager.getDiffString(TFile.path)

async getDiffString(filePath: string): Promise<string> {
     return (await this.git.diff([filePath]));
}

This doesn't work for this plugin because, as you said, only diffs the working dir to HEAD.

This is accessible already and will be useful for getting a comparison to the current state of the file compared to the latest commit, just like the recovery view does.

simple-git API

https://github.com/steveukx/git-js#api

API What it does
.diff(handlerFn) get the diff for all file in the current repo compared to the last commit
.show([options], handlerFn) Show various types of objects, for example the file content at a certain commit. options is the single value string or array of string commands you want to run

https://github.com/steveukx/git-js#git-log

I'd need an API for git log. That would need to return the hash, time and maybe also author. For simple-git, it accepts options.

options.file - the path to a file in your repository to only consider this path.

It accepts the path. I couldn't tell which data this method returns, but it would be great if it could return as much data as possible.

If it could return an array with objects, that should work.

interface commits { logReturn[] }
interface logReturn {
    hash: string,
    commitMessage: string,
    time: string | Date | number/*, whatever works*/,
    author: string
}

I'd also need an API to access .show.

Show can be used like this to display the content at a certain commit:
https://stackoverflow.com/a/338470

git show HASH:path/to/file.md

As parameters it needs the path and the commit hash.


I'd also need access to .diff that accepts a file path and the two commit hashes.

You use it already here https://github.com/denolehov/obsidian-git/blob/7cbff742b30d7a77cdc0e20c8b2fc385974d81fb/src/simpleGit.ts#L183

const diff = await this.git.diff([`${localCommit}..${upstreamCommit}`, '--name-only']);

Instead of --name-only it would need to accept a path.

@kometenstaub
Copy link
Owner

If you can provide these three APIs, then I should be able to integrate it into my plugin without breaking mobile compatibility for the other two views.

@kometenstaub
Copy link
Owner

Before that, I'd need to do more refactoring though.

Update: The refactoring is done.

@Vinzent03
Copy link

Vinzent03 commented Mar 18, 2022

@kometenstaub

Log

There is now a method log on gitManage accepting an optional file path as parameter. It returns a list of the following interface:

interface DefaultLogFields {
    hash: string;
    date: string;
    message: string;
    refs: string;
    body: string;
    author_name: string;
    author_email: string;
}

Simple git's api returns the count of commits and the latest commit too, but you can get these information by the list itself. Index 0 is the newest. An example for date: 2022-03-02T20:16:28+01:00.

Show

async show(commitHash: string, file: string) {
        return this.git.show([commitHash + ":" + file], (err) => this.onError(err));
    }

Diff

async diff(filePath: string, commit1: string, commit2: string): Promise<string> {
    return (await this.git.diff([`${commit1}..${commit2}`, "--", filePath]));
}

Example output:

diff --git a/.obsidian/app.json b/.obsidian/app.json
index 052cbd7..d6d141f 100644
--- a/.obsidian/app.json
+++ b/.obsidian/app.json
@@ -1,7 +1,4 @@
 {
   "promptDelete": false,
-  "readableLineLength": false,
-  "livePreview": false,
-  "legacyEditor": false,
-  "foldHeading": true
+  "readableLineLength": false
 }
\ No newline at end of file

Is that everything you need? It's not published/pushed yet. If you agree, I can release a new version.

@kometenstaub
Copy link
Owner

@Vinzent03 Yes, this should be everything I need. Thank you ❤️

@Vinzent03
Copy link

Released a new version 🚀

@kometenstaub
Copy link
Owner

Thank you, it is shipped! :)

@Azmoinal
Copy link

I don't see the command "Show Git diff history view for active file" on the iOS device. Is it normale? Reading this issue also on mobile, it should be available.

P.S. I've the Git plugin enabled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants