gitgit-patchgit-apply

how to see the file which would be committed


I have modified a file (or some files) in my directory, and I've used git add to stage some of the changes lines from the file, but not all the changed line.

I can use git diff --staged my-file to see the diff of what's changed. git diff --staged my-file ignores lines which were changed but not staged. Here is an example of the output of git diff --staged my-file

diff --git a/ens/cours/ens_cours_JN.csv b/ens/cours/ens_cours_JN.csv
index dcea574..ff33469 100644
--- a/ens/cours/ens_cours_JN.csv
+++ b/ens/cours/ens_cours_JN.csv
@@ -24,6 +24,7 @@ SCALIN_E;EPITA;préparation pédagogique;JN;ING1;2020-05-13;;False;True;PT4H;;
 SCALIN_E;EPITA;préparation pédagogique;JN;ING1;2020-05-20;;False;True;PT4H;;
 SCALIN_E;EPITA;préparation pédagogique;JN;ING1;2020-05-27;;False;True;PT4H;;
 SCALIN_E;EPITA;préparation pédagogique;JN;ING1;2020-06-03;;False;True;PT4H;;
+SCALIN_E;EPITA;préparation pédagogique;JN;ING1;2020-06-03;;False;True;PT4H;;commit this line
 THLR;EPITA;préparation pédagogique;JN;ING1;2020-07-20;;False;True;PT8H;;Recording TDs
 THLR;EPITA;préparation pédagogique;JN;ING1;2020-07-21;;False;True;PT8H;;Recording TDs
 THLR;EPITA;préparation pédagogique;JN;ING1;2020-07-22;;False;True;PT8H;;Recording TDs

Question: How can I generate the text of the file which would be committed? I'd like a check-in hook to eventually process that file before allowing the commit.

I suspect there is some simple incantation using git apply. However, a simple use of git apply produces the following diagnostic messages.

jnewton@Marcello cours % git diff --staged > ens_cours_JN.csv.patch
git diff --staged > ens_cours_JN.csv.patch
jnewton@Marcello cours % git apply ens_cours_JN.csv.patch
git apply ens_cours_JN.csv.patch
error: patch failed: ens/cours/ens_cours_JN.csv:24
error: ens/cours/ens_cours_JN.csv: patch does not apply

I have a solution that seems far too complicated.

  1. generate the .patch file with git diff --staged > my-file.patch
  2. save the original with cp my-file my-file.save
  3. stash the changes with git stash save my-file
  4. apply the patch with git apply my-file.patch
  5. saved the desired result with cp my-file my-file.to-commit
  6. restore the file to the pre-add state with mv my-file.save my-file
  7. restore the fiel to the post-add state with git stash apply

Now, my file.to-commit is a copy of the fill which would be committed. Is this really the correct way to do this? It seems like I'm doing too much work.


Solution

  • You can take advantage of the :[<n>:]<path> construct to access to corresponding staged blob, and just do

    git show :my-file
    

    As described here :

    :[<n>:]<path>, e.g. :0:README, :README
    A colon, optionally followed by a stage number (0 to 3) and a colon, followed by a path, names a blob object in the index at the given path. A missing stage number (and the colon that follows it) names a stage 0 entry. During a merge, stage 1 is the common ancestor, stage 2 is the target branch’s version (typically the current branch), and stage 3 is the version from the branch which is being merged.

    So git show :0:path/to/file or the shorter git show :path/to/file outputs the full staged version of the file.