git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [QUESTION] how to diff one blob with nothing

From
ZheNing Hu <adlternative@gmail.com>
Date
Aug 5, 2023, 08:27 UTC
Message-ID
<CAOLTT8SBAb8bAV3uCPJ-q2btNeatMjmtRzDkRASffN5xTS1M0g@mail.gmail.com>
In-Reply-To
<xmqqmsz6ljk4.fsf@gitster.g>
Junio C Hamano <gitster@pobox.com> 于2023年8月5日周六 03:00写道:
Show 55 quoted lines
>
> Taylor Blau <me@ttaylorr.com> writes:
>
> > On Fri, Aug 04, 2023 at 10:28:53AM +0200, Christian Couder wrote:
> >> On Fri, Aug 4, 2023 at 6:42 AM ZheNing Hu <adlternative@gmail.com> wrote:
> >>
> >> > Actually, there is no need to support a default empty blob.
> >> > For example, with the command "git diff --no-index <file> /dev/null",
> >> > it can compare a file with /dev/null, but it can only compare <file>
> >> > and not <oid>.
> >> > Therefore, using commands like "git diff <oid> /dev/null",
> >> > "git diff --no-index <oid> /dev/null", or even "git diff <oid> --stdin"
> >> > could potentially solve this issue.
> >>
> >> Maybe it would be clearer to have a new option, called for example
> >> "--blob-vs-file", for that then. It could support both:
> >>
> >> $ git diff --blob-vs-file <blob> <file>
> >>
> >> and:
> >>
> >> $ git diff --blob-vs-file <file> <blob>
> >
> > Hmm. This feels like a case of trying to teach 'git diff' to do too
> > much.
>
> Worse yet, I do not quite get the original use case in the first
> place.  What is the series of diff output that result in comparing a
> random pair of blob object names going to be used for?
>
> The reply to <ZMKtcaN7xYaTtkcI@nand.local> says that the original
> use case was to express the evolution of a single path since its
> creation until its removal, but the thing is, a diff with an empty
> blob and a creation or a deletion event are expressed differently in
> the patch output, exactly because the patch has to be able to
> express "before this change, a file with zero byte content was
> there" and "before this change, there was nothing at this path"
> (vice versa for contents-removal vs deletion).
>
> For that reason, I have a hard time to find any merit in the earlier
> complaint that said "can be achieved by manually adding them, but it
> is not very compatible with the original logic", whatever the
> "original logic" refers to.  If creation needs to be recorded as
> creation and not as a change from an empty and existing blob, there
> has to be something that needs to be manually done to turn the
> latter (which is the only thing "diff" between two blobs or even a
> blob and a file can give) into the former *anyway*.  Whatever the
> thing that is looping over the history/evoluation of a single path
> needs to have a three-arm switch for each iteration to deal with
> creation, modification, and removal, and iterating over the contents
> of the files and prefixing "+" or "-" on each and every line would
> be the _easiest_ part of such a necessary tweak to turn "diff
> between an empty contents and something else" into "creation or
> deletion of a file."
>

Okay, let me clarify the background for using an empty blob diff. Essentially, it is a git web diff interface that requires real-time calculation of the diff between files across multiple versions and rendering them. Due to some reasons, the higher-level component did not provide multiple versions of commits but instead provided blob OIDs (Object IDs).

Therefore, I expected to generate the diff results directly using the
"git diff <oid> <oid>" command. (I only care about the patch part
in the diff and don't really care about the related information of OIDs
in the diff output.) Everything went smoothly except when a blob
is created or deleted, as there is no direct way to obtain
the diff for a blob using the "git diff <oid> <oid>" interface. Initially,
I intended to generate a patch by diffing an empty blob
 (e69de29bb2d1d6434b8b29ae775ad8c2e48c5391) with the blob ID.
However, unlike the empty tree (4b825dc642cb6eb9a060e54bf8d69288fbee4904),
the empty blob does not exist in the git repository by default.

I had to create an additional empty blob for the purpose of performing the diff, but this goes against the design of the web-based diff interface, which is intended to be read-only.

So, I might explore methods like "git diff <oid> /dev/null" or
 "git diff <oid> --stdin", they are read only, but it does not
currently exist...

Regardless, I hope that the empty blob diff can simulate the effect of an empty tree diff:

git diff 4b825dc642cb6eb9a060e54bf8d69288fbee4904
diff --git a/.cirrus.yml b/.cirrus.yml
new file mode 100644
index 0000000000..4860bebd32
--- /dev/null
+++ b/.cirrus.yml
@@ -0,0 +1,22 @@
+env:
+  CIRRUS_CLONE_DEPTH: 1
+
+freebsd_12_task:
+  env:
+    GIT_PROVE_OPTS: "--timer --jobs 10"
+    GIT_TEST_OPTS: "--no-chain-lint --no-bin-wrappers"
+    MAKEFLAGS: "-j4"
+    DEFAULT_TEST_TARGET: prove
+    DEVELOPER: 1
+  freebsd_instance:
+    image_family: freebsd-12-3
+    memory: 2G
+  install_script:
+    pkg install -y gettext gmake perl5
+  create_user_script:
+    - pw useradd git
+    - chown -R git:git .
+  build_script:
+    - su git -c gmake
+  test_script:
+    - su git -c 'gmake test'

Thanks,
ZheNing Hu
Previous: Junio C HamanoNext: Konstantin Khomoutov
Message 13 of 15 in “[QUESTION] how to diff one blob with nothing”
  1. ZheNing HuJul 19, 2023
  2. Junio C HamanoJul 19, 2023
  3. ZheNing HuJul 26, 2023
  4. Junio C HamanoJul 26, 2023
  5. Taylor BlauJul 27, 2023
  6. ZheNing HuJul 28, 2023
  7. ZheNing HuAug 3, 2023
  8. Taylor BlauAug 3, 2023
  9. ZheNing HuAug 4, 2023
  10. Christian CouderAug 4, 2023
  11. Taylor BlauAug 4, 2023
  12. Junio C HamanoAug 4, 2023
  13. ZheNing HuAug 5, 2023
  14. Konstantin KhomoutovJul 27, 2023
  15. ZheNing HuJul 28, 2023

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.