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.
Viewing a list of the latest commits. If you want to see what's happened recently in your project, you can use git log . This command will output a list of the latest commits in chronological order, with the latest commit first.
To find a git commit id (or hash), you can simply use the git log command. This would show you the commit history, listing the commits in chronological order, with the latest commit first.
Solution. 2.1 git log to display all the commit_id, the first one is the last commit_id, copy it. 2.2 git show commit_id --name-only to display all the files committed in the specified commit_id. 2.3 Undo the last commit with git reset --soft HEAD~1 , move the mistakenly committed files back to the staging area.
# open the git config editor $ git config --global --edit # in the alias section, add ... [alias] lastcommit = rev-parse HEAD ... From here on, use git lastcommit to show the last commit's hash.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With