1

Let's say there are 4 files A, B, C, and D, of which the files A, B, C are committed on the main branch.

I now create a new branch (let's call it sub-branch), do git checkout sub-branch and make changes, and commit file D only.

But, when I push the changes committed on the file D onto the remote repository(Github) by running git push -u origin sub-branch, even the commits of files A, B, C are added to this branch.

I'd want only the changes committed on file D to be reflected in the newly created sub-branch, how do I accomplish this?

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
Prajwal Kulkarni
  • 1,480
  • 13
  • 22
  • What do you mean? Only `sub-branch` will have the changes made to `D`. – evolutionxbox Mar 28 '22 at 07:08
  • I mean I'd want to push the commits made only on `D` to `sub-branch` and not to push previous commits on A, B, C made on `main` branch. – Prajwal Kulkarni Mar 28 '22 at 07:11
  • 2
    That's not how branches work on git... if you don't want the previous commits then you need to create the branch on a commit before those unwanted commits. – evolutionxbox Mar 28 '22 at 07:12
  • When you create a new branch from the main branch (as you did in your case), you'll start from the point that the main branch is currently at. So all commits history will be there in the new branch as well. – zaibaq Mar 28 '22 at 07:35
  • 1
    Something that github does remarkably poorly is visualise where branches _branch off_ from each other. Try running `git log --branches --oneline --graph` locally, and you may get more idea of how things relate to each other. – IMSoP Mar 28 '22 at 11:31
  • Awesome, thanks a lot @IMSoP, this command helped me get the correct hash I had to reset to, was able to accomplish what I wanted. – Prajwal Kulkarni Mar 28 '22 at 12:09

4 Answers4

1

However, the commits have already been pushed to the remote main branch.

The new sub-branch will include one commit with only changes for D.

Its parent commit, however, will be from branch main (and the parent commit before that too)

That is what a chain of commits is: a directed acyclic graph (DAG)

When I created a PR from forked repo's sub-branch to the original repo's main branch, it showed that 4 files were changed instead of 1.

That would be because the target branch does not have those files yet.

As commented, a git log --oneline --graph --decorate --all --branches will show you that graph.

I'd want to know how do I get the hash of X

You can also use git merge-base:

git merge-base main sub-branch
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • But, it does contain the commits from the main branch too. When I created a PR from forked repo's sub-branch to the original repo's main branch, it showed that 4 files were changed instead of 1. – Prajwal Kulkarni Mar 28 '22 at 07:32
  • @PrajwalKulkarni I have edited my answer: double check your target branch. – VonC Mar 28 '22 at 07:35
  • Yes, that is correct, the target branch of the original repository does not have those commits merged yet. So does that mean it is not possible to create more than 1 PR with each PR containing separate commits and not have chained the previous unmerged commits? I, however, did see a few PRs created by another person(>1 PR) with different commits in each PR, hence I was wondering how do I accomplish the same. – Prajwal Kulkarni Mar 28 '22 at 07:42
  • @PrajwalKulkarni You might a branch which starts from the target branch (so without A, B, C) and create/modify D only, then PR that branch. – VonC Mar 28 '22 at 07:46
  • How do I go about it? Given that changes to A,B,C has been pushed to the forked repo and not yet merged to target the repo's branch. And, we are only talking about modifications here and no new files are created. Would appreciate it if you could update the answer with the details. – Prajwal Kulkarni Mar 28 '22 at 07:53
  • @PrajwalKulkarni `git switch -c newBranch targetBranch`: create a branch from the target branch which has the desired starting state. – VonC Mar 28 '22 at 08:00
  • @PrajwalKulkarni "I'd want to know how do I get the hash of X": git merge-base is handy for that. See my edited answer. – VonC Mar 28 '22 at 12:34
1

Branches are just pointers to commits. Suppose branch main contains these commits:

X-A-B-C

And main is pointing to commit C. When you created your new branch you started from main which is equivalent to starting from commit C:

git switch -c sub-branch main
# since main points to C this is the same as
git switch -c sub-branch C

Instead it sounds like you just need to create your new branch from an earlier commit instead:

git switch -c sub-branch X

Had you done that sub-branch would have ended up with X-D. Since you've already made the branch though, you can fix it by resetting it back to X and cherry picking D:

git switch sub-branch
git reset --hard X
git cherry-pick D
TTT
  • 22,611
  • 8
  • 63
  • 69
  • Thanks. While this almost works, I'd want to know how do I get the hash of X? If I do `git log` on the main branch it is only showing the hash of A. – Prajwal Kulkarni Mar 28 '22 at 08:49
  • @PrajwalKulkarni when you type `git log` you only see one commit? If yes, maybe your local `main` branch only has one commit, and perhaps that commit is `X`? If you only merged the other commits into the remote branch `main`, then you could try `git fetch` followed by `git log origin/main` to see the log for the remote `main` (and I assume one of those commits listed will be `X`). You could also update your local copy of `main` with `git pull` and then `git log` on your local copy of `main` should have it too. – TTT Mar 28 '22 at 14:07
0

A few options are:

  1. Checkout from remote (assuming the commits haven't been pushed).
  2. Checkout the branch before making changes A, B, C in main, then make change D in your newly created branch.
  3. Checkout from the particular commit before you made changes A, B, C git checkout -b <new_branch_name> <sha1>
Preston Martin
  • 2,789
  • 3
  • 26
  • 42
  • Thanks for the suggestions. However, the commits have already been pushed to the remote main branch. So, is there any way to go about from here? – Prajwal Kulkarni Mar 28 '22 at 07:19
  • What is your intent? Are you trying to undo your changes to main? I'm curious because it sounds like you are trying to do something unconventional to git. – Preston Martin Mar 28 '22 at 07:30
  • Ok, let me clear this up. So I had pushed some commits to the remote main branch a few days ago, today I created a new branch checked out to the new branch, changed and committed another file and pushed it to the remote origin's new branch. I expect only the file committed today to be reflected in the new branch and not include previously committed changes to other files that were pushed a few days ago to the main branch. – Prajwal Kulkarni Mar 28 '22 at 07:36
0

Before you checkout to a new branch make sure all of your changes are committed.

In case you do not want to commit either reset or stash your changes.

This will solve your problem.

And now If you commit anything in the branch D it will push only those changes.

Rajeev Bera
  • 2,021
  • 1
  • 16
  • 30