Jeebs24
Jeebs24

Reputation: 177

Get Git repository's last commit

I have a central Git bare repository. When a push is made to that repo I want to run a post-receive hook. What that hook will do is create a message on a Basecamp project (using their API). I want info on the update that was just performed. Right now I think git log -2 --stat is good enough but would like a little more info (branch that was updated, file created, files removed). Can anyone help with the command(s) I need to do to get all the info? Performing multiple commands is fine with with me, there probably isn't a single command that will get me all the information.

Upvotes: 8

Views: 1873

Answers (3)

Jonas Schäfer
Jonas Schäfer

Reputation: 20738

If there is no specific reason why you use post-receive, I would rather suggest using update, which gets the old ref, the new ref and the branch as command line arguments.

So you can just get the whole log using the git log commands suggested here and giving oldref..newref as argument (replacing oldref and newref respectively).

For more information see the githooks(5) manpage on the update hook. You even can abort the update at that point if you need to.

Actually, you get the same information in the post-receive hook on stdin. I do not see why you need to do a lot of find commands to accomplish that task.

Upvotes: 2

eckes
eckes

Reputation: 67157

You could find the latest commit by examining and sorting the files under .git/refs/heads: every time a new commit is made, the corresponding refs/heads file is changed, i.e. when committing to master, refs/heads/master is updated.

So, let's develop a solution.

First task: find all branches (i.e. all files under refs/heads and print out when they were last changed. You're talking about hooks, so we give the path relative to the .git/hooks directory:

find ../refs/heads -type f -printf '%T@ %p\n'

This produces a list of all branches along with their change date. See the man page of find for an explanation of the parameters.

Second Task: sort the obtained list

find ../refs/heads -type f -printf '%T@ %p\n' |\
sort

Third Task: we need the newest element in that list. Since sort sorts from old to new, our desired item is at the bottom of the list. Get this element with tail (only one item, therefore pass the -1 flag):

find ../refs/heads -type f -printf '%T@ %p\n' |\
sort    |\
tail -1

Fourth Task: drop the date in the obtained line. From our printf statement we know that date and path are separated with a space. Feed this as delimiter into cut (-d " ") and tell it we need the second field (i.e. the file path, -f 2). For convenience, we'll store this file path in a variable called $LATESTHEAD:

LATESTHEAD=$(\
    find ../refs/heads -type f -printf '%T@ %p\n' |\
    sort    |\
    tail -1 |\
    cut -d ' ' -f 2 )

Fifth Task: Now we know the filename, but we need the content. This is the latest revistion that could be passed to git log. cat does the job. Store the latest revision in $LATESTREV

LATESTHEAD=$(\
    find ../refs/heads -type f -printf '%T@ %p\n' |\
    sort    |\
    tail -1 |\
    cut -d ' ' -f 2 )
LATESTREV=$(cat $LATESTHEAD)

Now, you could use $LATESTREV to do any dirty things you want.

Perhaps not the most elegant solution (probably someone will come up and tell you a much easier one-liner) but works for me.

Upvotes: 3

Ben Roux
Ben Roux

Reputation: 7426

Adding --summary to your git log will produce the new and deleted file listing (git refers to them as "nodes"):

git log --stat --summary -1

To get the branch, try running:

git branch --contains `git log --oneline -1 |cut -f1 -d\ ` |cut -b3-

Note: I am testing this on my mac. Unix cut is 1 indexed but I believe Debian cut is 0 indexed. If so, and if you are on a Debian box, change -f1 to -f0 and the branch command should work just fine

Upvotes: 2

Related Questions