1

I am trying to setup CI/CD in a way that it kicks off testing only on files that have been added/touched. Essentially the work flow is as follows:

  1. A developer creates a branch from the production branch to test changes.

  2. They make certain changes, test locally, and then merge into the production branch.

  3. But, because there are various developers continuously merging changes, by the time you merge your changes there may be new directories or files in production.

So the following command would return changes between the development branch and the master branch while including whatever is missing on both sides:

git diff {my_development_branch} {master} --name-only -r

Let's assume I have these files in master:

A/file1
B/file2
C/file3

and I create a branch called my_development_branch which contains the same but now I have added a directory and file:

A/file1
B/file2
C/file3
D/file4

By this point the master branch may have new contents so it may look like:

A/file1
B/file2
C/file3
Z/file26

Using git diff will return D and Z but for my use cases I would like to only get files that I have added/touched which would only be D. Is there a way to get git to discern this information for me?

Zakariah Siyaji
  • 989
  • 8
  • 27
  • Note that commits do not contain changes, but rather hold *snapshots*. Each commit has a full copy of every file. To find "changes", you pick two commits—two snapshots—and ask Git: "what is different in snapshot 143, vs snapshot 900?" for instance. Your job here is to pick the *right snapshots*. Which snapshots are the right ones? That depends on your exact problem. – torek Dec 06 '22 at 08:25
  • *Branch names*, like `master` or `develop`, each pick one particular commit (one snapshot): each name picks the *latest* commit "on" that branch. So you need to work backwards from that latest commit to some earlier commit, to see "what changed since that earlier commit". This is where the three-dot syntax that [TTT mentions](https://stackoverflow.com/a/74695478/1256452) comes from. This syntax is a bit tricky; see [the gitrevisions documentation](https://git-scm.com/docs/gitrevisions) for one meaning, but [the `git diff` documentation](https://git-scm.com/docs/git-diff) for the other. – torek Dec 06 '22 at 08:27
  • Even a merge commit contains only a snapshot of the files (not changes to the files). What makes a merge special is that, from the merge commit, you can work backwards to *two* immediately-previous commits. – torek Dec 06 '22 at 08:29

1 Answers1

3

From the developer's point of view before the merge, you can use the 3-dot syntax version of diff:

git diff master...my_development_branch --name-only

That will show only the changes on my_development_branch since the merge-base between the two branches. That will usually be pretty darn close to what actually will change, but isn't necessarily perfect. To see what actually will change for sure, you need to actually do the merge. Immediately after the merge, you can use:

git diff @~1 @ --name-only

(@ is shorthand for HEAD, or also master in this case.)

Note: comparing the current (merge) commit with it's first parent only works if a new merge commit was generated when the feature branch was merged. In the case you described, a new merge commit would be created because the branch was out of date at the time of the merge. Since that's not always guaranteed to be true, many people recommend using --no-ff when merging into a shared branch such as master, so this comparison will always work. It also makes it to possible to see a clean graph of every merge into master with git log master --first-parent. Many tools default to --no-ff when completing a PR/MR into a shared branch for this reason.

TTT
  • 22,611
  • 8
  • 63
  • 69