1

I use a post-commit script to 'git archive' to a temp directory, then I use Rsync to move just the changed files to my dev working directory. I am preserving timestamps with rsync, but the git archive command updates all the timestamps to current date and time, so everything is getting pushed. According to the documentation (quoted below), It is only supposed to do that if I pass it a tree ID rather than a commit ID. I am not passing anything.

My git archive command to copy to temp:

git archive $branch | (cd $tempdir; tar x)

Here is what the documentation says:

"git archive behaves differently when given a tree ID versus when given a commit ID or tag ID. In the first case the current time is used as the modification time of each file in the archive. In the latter case the commit time as recorded in the referenced commit object is used instead. Additionally the commit ID is stored in a global extended pax header if the tar format is used; it can be extracted using git get-tar-commit-id. In ZIP files it is stored as a file comment."

Does this mean I need to get the commit ID and pass that to git archive? How do I do that?

I am a little confused? How do I archive to my temp directory without changing timestamps?

Thanks.

EDIT: I also tried these to no avail:

git archive get-tar-commit-id $branch | (cd $tempdir; tar x)

and

git archive $(git get-tar-commit-id) $branch | (cd $tempdir; tar x)

I am not sure what the proper syntax is. Maybe it is easier than I thought?

Doug Wolfgram
  • 2,064
  • 4
  • 27
  • 42
  • Any reason not to use a remote you could just push to? – D. Ben Knoble Aug 29 '19 at 18:12
  • Not sure I understand. the project is so large that rsyncing the entire code base it too slow. I just want each commit and push to push the changed files. Oh, and thanks for the edit Code Wizard. I forgot that. :) – Doug Wolfgram Aug 29 '19 at 18:16
  • Git doesnt push the whole project (after the first push). – D. Ben Knoble Aug 29 '19 at 18:23
  • Correct. It only pushes the changed files from my local machine to my server. Then I use a post-receive script to 'git archive' and subsequently. rsync it out to the development directory. It is git archive that is the problem. I am trying to only move changed files to the development directory because rsync is taking up to a minute moving everything. – Doug Wolfgram Aug 29 '19 at 18:25
  • I am open to other ideas on how to get only the changed files out of a git repo and move them to a working directory. – Doug Wolfgram Aug 29 '19 at 18:27
  • Doesn't matter whether you use a commit or tree. It's just that they choose a different timestamp, but both use the same timestamp for all files. So, even if you change just one file, you get a commit with a new timestamp, and `git archive` propagates that to all files that it puts in the archive. Can't you instruct rsync to inspect just the file contents, but not the timestamp? – j6t Aug 29 '19 at 18:58
  • "Can't you instruct rsync to inspect just the file contents, but not the timestamp?" Didn't know that was an rsync option. I'll check. – Doug Wolfgram Aug 29 '19 at 20:16

2 Answers2

2

One workflow I’ve used is to make a non-bare remote, and also

git config --local receive.denycurrentbranch true

Then the server can have a true working directory, which you can push to.

D. Ben Knoble
  • 4,273
  • 1
  • 20
  • 38
  • I found this: http://databio.org/posts/push_to_deploy.html. Since your reply was first in line I'll accept it as torek's is essentially the same response. Thanks! – Doug Wolfgram Aug 29 '19 at 20:51
1

If $branch is a branch name, it's resolved to a commit hash first, and then git archive archives the tree associated with that commit. Your existing git archive command is therefore doing what you wanted it to.

The problem is that the time stamps on all the files will be the date stamp on that commit. Every commit is, after all, a full snapshot of every file. So every file in the archive has the same time stamp: the time stamp from that commit. What you wanted git archive to do is not what you wanted to want git archive to do. :-)

If you have a fairly modern Git, set up the server with a non-bare repository in which you have set receive.denyCurrentBranch to updateInstead. (Then make sure no one ever does any work on the server! The point of a --bare repository is to enforce a lack of work-being-done.) Your work-tree on the server will then do what you really wanted.

torek
  • 448,244
  • 59
  • 642
  • 775
  • I understand this conceptually, but not practically. You mean I can set up a new git 'project' but instead of using bare, use receive.denyCurrentBranch that points to my dev directory and thus, all commits and pushes form the team go directly to the dev directory? No-one ever edits directly on the server in this case. – Doug Wolfgram Aug 29 '19 at 20:49
  • Close enough. The one sticky point is: you must `git checkout dev` on the server so that the work-tree on the server is that of the tip of `dev`. The `updateInstead` will make a push-to-`dev` cause the server to `git checkout dev` into that work-tree. (In theory, `git worktree add` should behave similarly, but I tested it a while back and it doesn't, so you have to set the "main" repo branch to the one desired branch here.) – torek Aug 29 '19 at 20:51
  • 1
    A minor side effect of doing `git checkout dev` on the server is that future clones *from* the server will, locally on the clone, create branch `dev` instead of `master`. That may be a plus, in your case. – torek Aug 29 '19 at 20:51