user3113427
user3113427

Reputation: 465

How can i get only the new files in git from other branch

I have TEST branch and then i have master branch.

I have folder called DATA with subfolders and files.

Now in my master i have

  1. new files which are not in TEST
  2. Files modified both in TEST AND master
  3. files in master but deleted in TEST

Now i only want to update TEST branch with new files from master branch so that everything else unchnaged for TEST branch but new files should be there.

I could do that easily with rsync but just thinking if that could be done in git

Upvotes: 0

Views: 70

Answers (1)

torek
torek

Reputation: 490178

You should be a bit careful with this as there are different answers to similar, but not exactly-the-same, questions. For instance suppose the commit history looks like this:

A - B - C   <-- master
  \
    D - E   <-- TEST

Here master and TEST start with a common commit, A, and then diverge. Let's suppose that the common commit A has these files (in directory DATA/ if you like, but I'll just name the files):

file_A1
file_A2

Suppose further that commit B adds file_B1 but deletes file_A2. Then, commit C adds file_C1 and modifies file_A1 slightly.

This means if you git checkout master you will get the three files (A1, B1, and C1) with the modified file_A1 contents.

Now suppose commit D modifies file_A1 and adds file_B1 and file_D1. Then commit E removes file_B1 and adds nothing else.

This means if you git checkout TEST you will get three files (A1, A2, and D1) with the modified file_A1 contents (which may be modified differently from the version in commit C, or could be the same as the contents in commit C).

When you ask about "files in TEST that are not in master", does file_A2 count? It's there if you git checkout TEST; it's not there if you git checkout master; but it was there in the common starting point, commit A.

When you wonder about "files modified in both": clearly file_A1 was modified in both. But what if the change was identical in both, so that file_A1 has the same contents regardless of which branch is checked out. Is that "modified in both", or not?

What git needs you to do to answer such questions is to choose whether to compare two specific revisions, or to consider something more like a three-way merge (what you'd get if you attempted to merge TEST and master using their merge-base, revision A, as a starting point).


git diff <options> master TEST

This will compare commit C (what master points-to, i.e., the "tip" of the master branch) vs commit E (the tip of branch TEST). So you'll compare the two file_A1s, and see that commit E has file_A2 and file_D1 and lacks file_B1.

The <options> part here may be empty, or may be as described below.


mergebase=$(git merge-base master TEST)
git diff <options> $mergebase master
git diff <options> $mergebase TEST

This does two separate diffs, of the merge-base (commit A) against master, and of the merge-base against TEST.

The first diff will show you that on branch master, the change from A to C is to modify file_A1, delete file_A2, add file_B1, and add file_C1.

This is the kind of operation git uses to figure out how to do a branch merge. In fact, there's a special syntax for running git diff against the merge-base of two branches, against the tip of one of those two branches:

git diff <options> TEST...master  # three dots

This does the same as the first diff (git diff <options> $mergebase master). To compare the merge-base to the tip of branch TEST:

git diff <options> master...TEST  # again, three dots

As for <diff options>, if you're not interested in the different contents of files, the obvious option to start with is --name-status, which prints the names and status-es of the files, and --no-renames, to turn off rename detection (unless you want rename detection, in which case, add -M instead).

Files will show up as added, deleted, or modified (A, D, and M status respectively) in terms of the change between the two trees you'd get if you checked out the commits chosen by the diff. There are more possibilities here though: T occurs if a regular file is replaced with a symlink or vice versa (and more special cases with submodules); C (plus a numeric similarity value) occurs if you add --find-copies-harder and/or -C options; and R (plus a numeric value just like C) occurs with rename detection. The C and R cases print not only the status and filename, but also the "origin file name".

You can add --diff-filter to select only particular occurrences: --diff-filter=A, for instance, will select only those files whose status is A (added).

Upvotes: 2

Related Questions