0

There are number of questions which try to map the CVS ability of cvs diff -D "1 days ago" to git:

Git - How can I list all files changed on the master branch between two times?

How can I get the diff between all the commits that occurred between two dates with Git?

But from my understanding from the comments in this question:

Does copying the Git bare repo change the log?

performing git diff --name-only master@{"5 day ago"} master is local to your machine and can not resolve issues with merges into master.

I'm thinking that I need to use git whatchanged and based on another question (Bash script to extract filenames from git whatchanged) perhaps

git show --pretty="format:" --name-only HEAD^

but at best I seem to be thinking I have to concoct a somewhat fragile script to parse various git outputs for particular refs falling within certain dates and then redirect those refs to other git commands to isolate what files were modified in those refs, and finally concat the results.

I just am shocked that this hasn't already been provided by git already as I feel it is a somewhat fundamental feature, particularly because, from the questions that I have mentioned above, git is not fully reproducing the wonderful advantages of cvs diff -D "1 days ago" and if CVS has something on git, then well, I've lost all faith in humanity.

Can someone prove me wrong? Is there a way to reliably query if any files in master have been updated, via a merge or commit, since a period of time?

The Problem

Here is what I did that led me here:

  1. Make a number of commits to your repository and push them to origin
  2. Now take the bare repository and copy it with cp -r --preserve
  3. From this copied bare repository, execute git clone copy_of_everything
  4. In copy_of_everything run git diff --name-only master@{"5 day ago"} master or however long its been since you made those commits in step 1.

You will find, at least I did, that the git diff --name-only master@{"5 day ago"} master is unable to find any commits not done since you performed the clone.

This is what seems so unacceptable. The logs are there telling me what I need to know in long-form, but no one or two commands that I am aware of can tell me which files have been modified since a certain date.

Update 1

sleske's comment seems to hit the nail on the head. git diff --name-only master@{"5 day ago"} master, being based on the reflog, is a bad idea because it's based on local modifications to the repository state.

So is there a nice alternative?

Also, kudos to User:qqx for pointing me in this direction with this question in the first place.

Update 2

And there is. And sleke's (now accepted) answer explains why.

In short, I needed to perform:

git diff --name-only $(git log --until="1 days ago" -n1 --format=%H master ) master

Faith in humanity restored.

Community
  • 1
  • 1
EMiller
  • 2,792
  • 4
  • 34
  • 55
  • Note that you are mixing up two kinds of logs: The *list of commits* (printed by `git log` etc.), and the *reflog* (which lists where a certain branch pointed to at different points in time). While these will be the same if you just keep committing to a branch, they are different in general. `master@{some date}` uses the reflog. Also note that the reflog is meant as a safety net, it's not permanent, so normally you won't use it. – sleske Feb 16 '13 at 03:35
  • Exactly what I was afraid of. *reflog* is too ephemeral. Then all those posts mapping `cvs diff -D "1 days ago"` to `git diff --name-only master@{"5 day ago"} master` are either making a bad choice in using the reflog to answer this question or else there's nothing out there in git-land that easily works. – EMiller Feb 16 '13 at 03:40
  • 1
    Yes, using the reflog is almost always a bad idea, unless you want to reset your repository to a previous state, e.g. to recover commits you discarded. It does not show repository history, but the history of your *local modifications* to repository state. – sleske Feb 16 '13 at 03:42
  • If I may venture some advice: Read up on git's reflog, it's a useful tool, but needs a bit of reading and playing around to understand. One good explanation is in the book "Pro Git", ch. 9: http://git-scm.com/book/ch9-7.html . If you have time, read the whole book - it's quite short, and worth it. – sleske Feb 16 '13 at 03:51

2 Answers2

1

Unfortunately, I'm not very familiar with cvs diff -D. I assume it shows all changes made to files since the time given. If you want that with git, you can do:

git log --until="1 days ago" -n1 --format=%H

This will print the last commit on master that is older than 1 day.

Then use the ID of that commit to get a diff between the commit from one day ago, and the current HEAD (i.e. current state of the branch):

git diff <ID from step before> HEAD

This will print a full diff. To just get a list of files, add option --stat to the end. This will give you a summary, like:

 a/data.c      |  14 ++++++++
 b/stuff.c     |   2 +-
 b/code2.c     |  54 +++++++++++++++++------

I don't know any way to do it with a single command; of course you could just combine both in one line (assuming you use bash):

git diff $(git log --until="1 days ago" -n1 --format=%H) HEAD 

Note: This will also pick up changes to files caused by a merge. It just compares the states of the repository at the two commits given (old commit, and HEAD).

sleske
  • 81,358
  • 34
  • 189
  • 227
  • But is this only for one commit? What if there were multiple commits since yesterday? – EMiller Feb 16 '13 at 03:33
  • No, `git diff ` will print the differences between these two commits - this will include any changes by commits inbetween. I edited my answer to explain. – sleske Feb 16 '13 at 03:38
  • Note that in git, unlike CVS, each commit is best thought of as a snapshot of the *whole tree* - so comparing commits will compare the state of the whole tree. – sleske Feb 16 '13 at 03:39
  • Sorry I meant to ask, in my original comment, can I only do this relative to one commit? I'm still looking for a way to show which files have changed relative to a date, regardless of the number of commits that have happened since that date. – EMiller Feb 16 '13 at 03:42
  • 1
    @User7391: I think this is a misunderstanding. The commands from my answer will list all files which changed since the date given - regardless of the number of commits since that date. It's just that `git diff` does not directly take a time range parameter, so you must find the right commit first (the last commit before the point in time you are interested in). Then you use `git diff` with that commit, to compare the state as of that commit with the current state. – sleske Feb 16 '13 at 04:01
  • I think you are absolutely right. I get exactly what I want with `git diff --name-only $(git log --until="1 days ago" -n1 --format=%H) master`. Am I correct that replacing `HEAD` with `master` will only apply this query to the master branch? – EMiller Feb 16 '13 at 04:10
  • @User7391: As written, the query will apply to the current branch. If you want to do it for a different branch, you must put the branch name both into the `log` subcommand and replace the `HEAD`. E.g. `git diff --name-only $(git log --until="1 days ago" -n1 --format=%H MYBRANCH ) MYBRANCH ` – sleske Feb 16 '13 at 04:15
  • Yes. This solves everything. Thanks for the related question. In my defense, my question and your answer, indicates why `git diff 'master@{1 day ago}` gives the warning in the related question. – EMiller Feb 16 '13 at 04:25
0

git diff "master@{a month ago}".."master@{last week}" gives the differences between those dates from the reflog, do a whatchanged and a bit of post-massage will give you the changed files.

sleske
  • 81,358
  • 34
  • 189
  • 227
vonbrand
  • 11,412
  • 8
  • 32
  • 52
  • -1 this is incorrect in general (though it may work sometimes). This will use the reflog, which may not have an entry for every commit. E.g. if you pulled all commits of the last two months in one go, they will not have entries in the reflog. – sleske Feb 16 '13 at 03:44
  • 1
    Actually, I'm taking back the downvote. This is the right answer, *if* the date refers to the reflog (which may or may not be appropriate). This is nicely explained in this answer: http://stackoverflow.com/a/1161712/43681 – sleske Feb 16 '13 at 04:20