Reputation: 21
I am trying to get the files changed in the last commit in git and put them into a separate folder. Is there an ant script or shell script that does this job?
To give you a context, I am trying to implement a continous integration and delivery pipeline to release only the changed files in a git branch to salesforce environment. I am making use of ant build.xml and force.com migration tool to achieve this. The git branch currently contains the full metadata of sandbox . I dont want to deploy the entire metadata when doing a release - hence the requirement to get only the changed files and deploy only those files to the target salesforce environment.
Any help would be appreciated. I am kind of blocked at this stage with no clue how to proceed.
Upvotes: 2
Views: 2816
Reputation: 489478
Let's start with a human-oriented answer, but note that you're trying to build something that a machine will do, and machines are generally very fast idiots that follow your directions even if you have hit a weird case where they should do something smarter.
Assuming you have the full repository (or at least a shallow repository with enough commits), use git diff --name-only
or git diff --name-status
to extract the names of the files of interest:
$ git diff --name-status master~1 master
M Documentation/RelNotes/2.19.0.txt
for instance tells me that between the commit one graph-step in the first-parent direction before the current master
, and master
itself, exactly one file changed, via modification.
The two commits being compared here are the result of git rev-parse
on each of these two arguments, so if you have hash IDs, you're in better shape than if you just have a branch name. Branch names move in ways that may not be predictable, i.e., there's no obvious guarantee that your previous deployment was master~1
. Commit hash IDs do not: if you know that you previous deployment was, say:
$ git rev-parse master
b7bd9486b055c3f967a870311e704e3bb0654e4f
and at some point in the future your next deployment is some other commit whose hash ID you obtain (perhaps via git rev-parse
just like this), it does not matter if someone did something scary with the name master
, such as to rewrite commit history, you can still compare the correct two commits.
Now let's get into some of the complications.
Let's pick two different commits to compare:
$ git diff --name-status 3c6151dad310db71f599dbfbac329fa961f29794 979f030359f6830fbaebd0c76e9aad5f86993fef
M .gitignore
M .mailmap
A .travis.yml
M Documentation/CodingGuidelines
Three files here were modified as usual, but one, .travis.yml
, is new. It was created, not changed, across this commit-pair.
(I snipped a lot out here.)
R100 t/t5701-clone-local.sh t/t5605-clone-local.sh
R100 t/t5702-clone-options.sh t/t5606-clone-options.sh
R100 t/t5704-bundle.sh t/t5607-clone-bundle.sh
R100 t/t5705-clone-2gb.sh t/t5608-clone-2gb.sh
R100 t/t5706-clone-branch.sh t/t5609-clone-branch.sh
R100 t/t5707-clone-detached.sh t/t5610-clone-detached.sh
R063 t/t5708-clone-config.sh t/t5611-clone-config.sh
R100 t/t5709-clone-refspec.sh t/t5612-clone-refspec.sh
R099 t/t5710-info-alternate.sh t/t5613-info-alternate.sh
These files were renamed.
D t/t5700-clone-reference.sh
This file was deleted.
There are other statuses you can come across, and you should decide what to do with them.
git diff
is a porcelain command; you want plumbing commandsYou need to do a machine reading of the output from git diff
, but git diff
is—as unlikely as it might seem from these examples—actually aimed at producing output readable by humans, rather than output readable by machines. Git calls these user-oriented commands porcelain, with the machine-oriented ones called plumbing.
This has several side effects. The most important is this one: User configurations change the way git diff
output appears.
In particular, that status of R
(for renamed) appears if and only if you enable rename detection. Rename detection is controlled by the user's diff.renames
and diff.renameLimit
settings by default. The underlying defaults, should the user not have configured a setting, depend on the Git version as well. So instead of git diff
, you should use git diff-tree
, which is a plumbing command.
It is more obnoxious to use, because you have to specify everything, especially the -r
(recursive) flag to find out what is different inside different sub-trees. You should also probably use the -z
flag to have it zero-terminate file names, so that you can handle those reliably in all cases.
If you use submodules, think about how you want to deal with those.
In all cases, read the git diff-tree
documentation carefully.
Upvotes: 2