3

The command git show --pretty="format:" --name-status bd61ad98 will show a list of all the files modified/added/deleted in the last commit where bd61ad98 is the commit ID. The output looks like this:

[trusktr@rocketship express.git]$ git show --pretty="format:" --name-status bd61ad98

A       test.txt
D       test3.txt
M       wp-atom.php

What about a command that shows the same information but for all the commits from the last push? FOr example, if a file was deleted (D), then re-added (A), then modified (M), the ideal status would be M for modified. In other words, the net effect is that the file was modified.

Is there any such command? Even if the command were to list the duplicate statuses for files, that'd be fine. I could write a script that can determine the net effect.

Perhaps there's a way to compare diffs and output a list of files modified/deleted/added?

The reason I need such a file is that I'm making a script that will update another location using FTP based on this info.

trusktr
  • 44,284
  • 53
  • 191
  • 263

2 Answers2

3

You really want git diff-tree; see my other answer to your other question, too. :-)

Edit for details:

git diff-tree -r [other options] commit1 [commit2]

will give you the changes (in the formats documented for git-diff-tree) made either between commit1 and (I think) its immediate parent (if commit2 is omitted), or between commit1 and commit2.

You can also give it an actual tree-ID but then you must give it both tree IDs since it will not be able to find the parent, e.g.:

git diff-tree -r 69d8f48dd3e69f228b9a727cc69f8fbaf4534b4f
error: Object 69d8f48dd3e69f228b9a727cc69f8fbaf4534b4f is a tree, not a commit

(obviously the ID will vary).

If you have a branch name that refers to "what we last sent out", e.g., branch THEYHAVE, and you want to send them what's on branch TESTED, you could do:

git diff-tree -r THEYHAVE TESTED |
    while read omode nmode ohash nhash letter pathname; do
        ...
    done

and use the various letter codes and values in $nhash and so on to extract the files ("git cat-file -p $nhash" will get you the contents of the file even in a --bare repo).

(You can simplify this with --name-status for your case, probably.)

Once you have everything FTP-ed to where it should go, you can then use git update-ref to move the branch-label THEYHAVE to whatever the branch named TESTED names (it might be a good idea to use git rev-parse once to grab the ID of that branch "up front", in case it moves while you're doing all this work).

torek
  • 448,244
  • 59
  • 642
  • 775
  • Sweeeet, `git diff-tree --name-status master` does exactly the trick... Let me see how it does with several commits. – trusktr Mar 11 '12 at 06:50
  • Hey, what about for a bare repository? `git diff-tree --name-status master` doesn't work on a bare repository. What can I do in that case? – trusktr Mar 11 '12 at 07:08
  • 1
    You can in fact use diff-tree in a bare repo, but you must give it two tree objects. I did not flesh things out much in the other reply either but in general you will want to know "what's on the now-out-of-date machine" (call that RevOld) and "what's in the branch that we want to run on the machine" (RevNew), and you'd "git diff-tree -r ... RevOld RevNew". An easy way to keep track of "what was on it" is to use a branch name. Once the data are in place, move the branch to RevNew. – torek Mar 11 '12 at 07:14
  • I think `git diff-tree --name-status xxxxxxx` shows the differences in the last push, where `xxxxxxx` is the push ID. – trusktr Mar 11 '12 at 07:30
  • 1
    See much-expanded answer above :-) – torek Mar 11 '12 at 07:51
  • Thanks for the details. Alright, so a good question would be how do I determine the ID of the tree that from a specific push? Is that possible? If i can determine the ID of the trees at two difference pushes, I'd be good to go! – trusktr Mar 11 '12 at 08:16
  • Well, now you're getting into details that will depend on how you want to use this thing. For instance, do you have a `--bare` repo that people push changes to, and you always want all changes to automatically go live immediately? Or, do you have a repo that has dozens of branches for development, and after testing, you want a specific tested rev to go live? Or, do you want to update the server once a day, or ... etc. – torek Mar 11 '12 at 08:19
  • I have a --bare repo that people push changes to, and yIou always want all changes to automatically go live immediately. – trusktr Mar 11 '12 at 08:58
  • In that case, you'll want a to write a post-receive hook, or to modify an existing post-receive hook, such as the sample one that sends email with changes. These hooks are moderately painful to use: you read changes from `stdin` and they come as groups of . You'll need to consider the case of a single push with (e.g.) 3 separate commits followed by one added tag followed by one added annotated tag with a new branch creation, etc., for the general case. See the email generator one... – torek Mar 11 '12 at 09:01
  • Oh, ok, so I can use `refs="$3" oldrev="$1" newrev="$2"` in the hook to refer to those parameters? I'll have to try it. In my situation though, the users pushing don't know anything about git. There workflow will consist of the custom commands `commit "message"`, `push`, and `pull` (PHP scripts), so essentially all they are doing is pushing nothing but commits (no branches or anything more complicated, just master). – trusktr Mar 11 '12 at 17:35
  • Wait, nevermind about `refs="$3" oldrev="$1" newrev="$2"`. I have to read from stdin... I gotta figure that out. :D – trusktr Mar 11 '12 at 18:32
  • Awwwwww Yeah, I got it working with PHP. Perfect. So i have the oldrev and the newrev IDs and I can now determine the files to send (using ftp) by seeing the changes with diff-tree. :D:D:D:D:D:D:D:D – trusktr Mar 11 '12 at 18:38
  • 1
    I had to go to bed last night, sounds like you have things working at this point though. Just consider Murphy and his law: when you think it's all working great, someone else in your group will figure out git and start making branches and stuff. :-) That's why I recommend coming up with some sort of general-purpose scheme, rather than simply ftp-ing over everything that was changed in the most recent push(es). – torek Mar 11 '12 at 19:17
  • After knowing the oldrev and the newrev, the command `git diff-tree -r --name-status ` shows exactly the info needed to know what to FTP over to my remote location. Sweet. – trusktr Mar 11 '12 at 19:38
  • About the FTPing, true: We'll have to lay some ground rules though. hehe. I don't really have time for a general purpose scheme though. I need to get this done like right now. hehe (maybe in the future I can add on to it though. After all, I'm gunna publish this on github :D) – trusktr Mar 11 '12 at 19:40
0

I don't know the exact diff format but here is what you can do in your script:

  • git fetch Note: Do not pull, but fetch.
  • Do the diff between <branch> and <remote>/<branch> in the format that you like, and store the results or take the required action.
  • Merge <remote>/<branch> into <branch>

This way, you can take actions on separate pushes.

Sailesh
  • 25,517
  • 4
  • 34
  • 47