1

Scenario:

I have branched off of the master branch(we'll call this new "branch-a"), and I have code I've committed to branch-a but have not merged it into master. Now co-worker has branched off of branch-a to build on my work(we'll call this "branch-b") and commits his work, pushes it to GitHub. GitHub shows his PR as all of my changes(branch-a) and his changes(branch-b) as new files/commits.

Question:

Is it possible for my co-worker's branch to only show the changes he made? He could wait till I merge my code, then no problem we know. But just curious if this is possible to show the diff in the PR.

alphapilgrim
  • 3,761
  • 8
  • 29
  • 58

1 Answers1

1

Is it possible for my co-worker's branch to only show the changes he made?

No. Consider, for instance, what happens if you added an entirely new file—let's call it alphapilgrim.txt—and then he modified that file. What would his change be, without the existence of that file in the first place?

Why this has to be the case

More deeply, Git itself stores each commit as a snapshot: a new, complete, separate copy of the entire source. Under the covers, the files actually get shared from one snapshot to another, but at least in the logical overview, each snapshot is quite independent of any previous or subsequent snapshot—with just one exception: each snapshot also refers, by "true name" (hash ID), to its parent snapshot.

The true name hash-ID of each snapshot is absolutely, totally, 100% guaranteed to be unique to that snapshot, yet identical across all identical copies of that snapshot. In fact, this is true for all Git objects, including "blob" (file storage) objects.1 This idea is central to Git's operation, both internally (within commits and such) and externally (fetching and pushing commits and making pull requests).

Hence, what happens with a pull request is that you, the request-ee, hand over access to your repository and a particular commit. That commit has a unique hash ID, which lets Git access its parent commit. The parent has a unique hash ID, which lets Git access that commit's parent—your PR's grand-parent, as it were. The grandparent has a unique hash ID, which lets Git access ... well, one hopes you get the idea here. :-) This process repeats until whoever it is gets to a commit they already have, and they know they have it because, well, they have it: they have a commit with that ID.

Hence, to make a PR that doesn't depend on your commits, your co-worker (Mr. or Ms. Co, perhaps?—you said "him"; I will call him "M.Co") must replace / rework his current series of commits that leads back to your commits that lead back to the shared-by-all commits. M.Co can make a new series of commits that is similar to M.Co's original commits, except that they branch off from the shared base.2

The main Git command that copies a series of commits to a new base is git rebase. After it has copied those commits, it changes the branch name, which currently points to the last of the original commits, to point to the last of the copies. Once M.Co has rebased his commits, he/she can make a new pull request from them. Now the pull-ee will obtain the latest commit, look at its parent ID, look at the parent's parent, and so on, until reaching a shared commit—and chasing this chain will not find any of your commits.


1See How would Git handle a SHA-1 collision on a blob? and Hash collision in git for additional information. It's possible to brute force attack the Git hash, and older versions of Git ... well, they don't fail entirely, but they do behave quite badly: your new commit is invalid or perhaps never made, and there is sometimes no warning that this is the case. The existing commits are all just fine, but if you have to git reset --hard to toss out a broken commit, that's not good. All but the colliding file are recoverable, but only with a certain amount of pain.

2It's at this point that M.Co realizes that he has modified alphapilgrim.txt and literally cannot rebase this way. Unless, of course, he hasn't done anything so terrible. But in either case it's M.Co's job to adapt his changes to the older base, minus whatever you did to arrive at your snapshot upon which he based his original commits.

torek
  • 448,244
  • 59
  • 642
  • 775