How do you move committed changes from a branch to master as pending changes?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















I was implementing a new feature, for which I created a new branch, and made a few commits onto it, and pushed. I now wish to continue working on this feature in master, in the form of pending / uncommitted changes. Pending because it needs more work before I commit. How do I do this?



When I finally commit, the revision history of master should just indicate one commit, as if I never created another branch or made intermediate commits. How do I do this?



The manual way is to create a second git workspace, open master in one and the branch in the other, and copy-paste each modified file. Is there an automated way of doing this?










share|improve this question


















  • 1





    Why not just continue working on the branch you've already created? You can squash everything down to a single commit when you're done before you merge it into master.

    – larsks
    Jan 3 at 2:27











  • I generally like to code in diff view, with the head of master in the left pane and my code in the right pane, so I'm aware of what changes I'm making. This doesn't work in a branch because the left side of the diff in Xcode no longer shows the head of master; it shows the head of the branch.

    – Vaddadi Kartick
    Jan 3 at 3:27




















1















I was implementing a new feature, for which I created a new branch, and made a few commits onto it, and pushed. I now wish to continue working on this feature in master, in the form of pending / uncommitted changes. Pending because it needs more work before I commit. How do I do this?



When I finally commit, the revision history of master should just indicate one commit, as if I never created another branch or made intermediate commits. How do I do this?



The manual way is to create a second git workspace, open master in one and the branch in the other, and copy-paste each modified file. Is there an automated way of doing this?










share|improve this question


















  • 1





    Why not just continue working on the branch you've already created? You can squash everything down to a single commit when you're done before you merge it into master.

    – larsks
    Jan 3 at 2:27











  • I generally like to code in diff view, with the head of master in the left pane and my code in the right pane, so I'm aware of what changes I'm making. This doesn't work in a branch because the left side of the diff in Xcode no longer shows the head of master; it shows the head of the branch.

    – Vaddadi Kartick
    Jan 3 at 3:27
















1












1








1








I was implementing a new feature, for which I created a new branch, and made a few commits onto it, and pushed. I now wish to continue working on this feature in master, in the form of pending / uncommitted changes. Pending because it needs more work before I commit. How do I do this?



When I finally commit, the revision history of master should just indicate one commit, as if I never created another branch or made intermediate commits. How do I do this?



The manual way is to create a second git workspace, open master in one and the branch in the other, and copy-paste each modified file. Is there an automated way of doing this?










share|improve this question














I was implementing a new feature, for which I created a new branch, and made a few commits onto it, and pushed. I now wish to continue working on this feature in master, in the form of pending / uncommitted changes. Pending because it needs more work before I commit. How do I do this?



When I finally commit, the revision history of master should just indicate one commit, as if I never created another branch or made intermediate commits. How do I do this?



The manual way is to create a second git workspace, open master in one and the branch in the other, and copy-paste each modified file. Is there an automated way of doing this?







git branch rebase feature-branch






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 3 at 2:24









Vaddadi KartickVaddadi Kartick

1,77552435




1,77552435








  • 1





    Why not just continue working on the branch you've already created? You can squash everything down to a single commit when you're done before you merge it into master.

    – larsks
    Jan 3 at 2:27











  • I generally like to code in diff view, with the head of master in the left pane and my code in the right pane, so I'm aware of what changes I'm making. This doesn't work in a branch because the left side of the diff in Xcode no longer shows the head of master; it shows the head of the branch.

    – Vaddadi Kartick
    Jan 3 at 3:27
















  • 1





    Why not just continue working on the branch you've already created? You can squash everything down to a single commit when you're done before you merge it into master.

    – larsks
    Jan 3 at 2:27











  • I generally like to code in diff view, with the head of master in the left pane and my code in the right pane, so I'm aware of what changes I'm making. This doesn't work in a branch because the left side of the diff in Xcode no longer shows the head of master; it shows the head of the branch.

    – Vaddadi Kartick
    Jan 3 at 3:27










1




1





Why not just continue working on the branch you've already created? You can squash everything down to a single commit when you're done before you merge it into master.

– larsks
Jan 3 at 2:27





Why not just continue working on the branch you've already created? You can squash everything down to a single commit when you're done before you merge it into master.

– larsks
Jan 3 at 2:27













I generally like to code in diff view, with the head of master in the left pane and my code in the right pane, so I'm aware of what changes I'm making. This doesn't work in a branch because the left side of the diff in Xcode no longer shows the head of master; it shows the head of the branch.

– Vaddadi Kartick
Jan 3 at 3:27







I generally like to code in diff view, with the head of master in the left pane and my code in the right pane, so I'm aware of what changes I'm making. This doesn't work in a branch because the left side of the diff in Xcode no longer shows the head of master; it shows the head of the branch.

– Vaddadi Kartick
Jan 3 at 3:27














3 Answers
3






active

oldest

votes


















3














First, I'll give the commands, then what they are really doing and why this achieves what you want. I assume below that the feature branch is just called branch—change the name given to git merge if it has some other name.



git status               # and make sure everything is committed on your branch
# do any extra commits here if required

git checkout master # change the current branch/commit, index, and work-tree
git merge --squash --no-commit branch


(In git merge, --squash implies --no-commit anyway, so you can omit the second flag argument here. I included it more for illustration. Moreover, --squash means do the merging action in the index and work-tree, but don't make a merge commit.)



You may, depending on your tools, want to do git reset (which defaults to a --mixed reset with HEAD as the commit) to copy the HEAD commit back into the index, so that plain git diff shows you everything, and git status shows everything as not staged for commit.



Long



It's important to note, here, that there isn't really such a thing as pending changes. Git doesn't store changes at all. What Git stores are commits, and each commit is a complete snapshot of all files. When you ask Git what changed, you must tell Git about two commits, or at the least, two trees-full-of-files. Git then figures out, from those two inputs, what's different in snapshots A and B. Then Git tells you those differences—but A and B remain full snapshots. In some ways, none of this matters—you see changes when you want, and snapshots when you want. But if your mental model matches what Git really does, you'll have fewer mysteries to solve: your own job will be easier. The most important way this matters is to remember: In order to see changes or differences, you must provide two inputs. Sometimes, one of those inputs is implied. Sometimes, both of them are implied!



This last is the case with a simple git diff or git diff --cached / git diff --staged: Git compares the index to the work-tree (plain git diff), or the HEAD commit to the index (--staged or --cached). The option, if any, determines the two inputs. That is, Git takes two of the three things from this list:




  • the HEAD commit, which is a real commit, containing all files in the special Git-only, frozen/read-only form;

  • the index, which is essentially the proposed next commit, and contains a copy of all the files, also in the Git-only form but not quite frozen;

  • the work-tree, which has your files in their ordinary useful form.


With two of these things in hand, Git compares them and tells you what's different. The git status command runs, as part of its job, both of these two git diffs (with certain options always set, such as --name-status and --find-renames=50%) and summarizes the results: the output from git diff --staged are changes staged for commit and the output from git diff are changes not staged for commit.



You can also manually run git diff HEAD. This chooses HEAD and your work-tree as the two inputs: you explicitly named one of them, HEAD, in the arguments, and the other is implied. That compares the frozen HEAD contents to the unfrozen, normal-format, work-tree contents, and shows you the difference. Again, Git is comparing full snapshots: the second one is the live work-tree, snapshotted by the process of diffing.



(Aside: what you want to do, in my opinion, is probably the wrong way to go about it. You can often make your own job easier by committing early and often. Doing diffs is a good idea, but you can do them from base-commit to tip-commit, i.e., across a span of commits, to assess the overall result. You can then use a interactive rebase, or—my preferred method—additional branches, to reconstruct the smaller commits into a more sensible series of commits. But much of this is personal preference. It sounds like your Xcode tool could work a lot better than it is doing; the way you're using it is not wrong, it's just terribly limiting.)



How and why this works



I started writing a longer post but it got out of hand, so I'll just say: see some of my other StackOverflow answers for how Git makes commits out of the index, not the work-tree, and how these commits update the branch name to which HEAD is attached.



Git's merge is itself also a pretty big topic. However, we can say that merging uses the index to achieve its merge result, with the work-tree playing a secondary role, mainly for the case where there are merge conflicts.



A real merge—that is, a git merge that does a full three-way merge and will, in the end, make a new commit of type merge commit—makes its new commit with two parents. These two parents are two of the three inputs that went into computing the merge result. The third input is implied by the other two; it's the merge base. Git finds the merge base on its own, using the commit graph. Git then compares the merge base to the --ours and --theirs branch tips, as if using two git diff --find-renames commands: one from base to ours, one from base to theirs.



Ignoring issues like added, deleted, or renamed files, the comparison of these three commits produces a list of who changed which files. If we changed some file that they didn't change, or they changed some file that we didn't, merging these is easy: Git can just take our file, or their file. If neither of us changed the file at all, Git can take any of the three versions of the file (merge base, ours, or theirs).



For the difficult case—we both changed some file—Git takes the merge base to start with, and combines our changes and their changes and applies the combined changes to the merge-base copy. If our changes and their changes touch different lines, the combining is straightforward and Git declares the result a success (even if it makes no sense in reality). If we and they both changed the same lines, Git declares a merge conflict.



The merge conflict case is the messiest. Here, Git leaves all three input files in the index, and writes the conflicted merge to the work-tree. Your job, as the human running git merge, is to come up with the correct merge, however you like. You can use the three index copies of the file, or the work-tree copy, or all of these. You resolve the merge yourself and then use git add to write the correct result into the index, replacing the three unmerged copies with a single merged copy. That resolves this conflict; once you have resolved all conflicts, you can finish the merge.



If you run git merge with --no-commit, Git will do as much merging as it can on its own—which might be all of it—and then stop, the same way it would for a merge conflict. If there were no conflicts, this leaves both the index and work-tree in a ready-to-commit state. (If there were conflicts, the --no-commit option has no effect: Git was already going to stop, with the mess left behind, and still stops, with the mess left behind for you to fix.)



In all of these cases, though, Git leaves behind a file in the .git directory, telling Git that the next commit—whether from git merge --continue or git commit—should have two parents. That makes the new commit a merge commit, which will tie together the two branches:



             I--J   [master pointed to J when we started]
/
...--F--G--H M <-- master (HEAD)
/
K--L <-- branch


That's not what you want. So, we use git merge --squash, which tells Git: Do the merge work as usual, but instead of making a merge commit, arrange for the next commit to be an ordinary commit. That is, if Git were to make a new commit M, it would look like this:



             I--J--M   <-- master (HEAD)
/
...--F--G--H

K--L <-- branch


For no particularly good reason, --squash inhibits the commit even if the merge goes well. So after git merge --squash, the index and work-tree are updated, but you can make more changes to the work-tree, use git add to copy the updated files into the index, and only when you are done, use git commit to make the new commit.



(For a more trivial merge, where Git would default to doing a fast-forward, --squash inhibits the fast-forward mode as well, as if by git merge --no-ff. So --squash, without --no-ff and without --no-commit, suffices.)



The final git reset, if used and needed, just copies the HEAD commit back into the index. That is, you probably want your tool to compare the HEAD commit to the work-tree, as if you were running git diff HEAD. If the tool compares the index to the work-tree instead, you can get the same effect by de-updating the index to match HEAD, after the --squash operation updated it.






share|improve this answer
























  • I upvoted this. Also thanks so much for the effort to help a stranger!

    – Vaddadi Kartick
    Jan 4 at 4:27



















1














Have you considered doing a merge into master and then using your preferred diff tool to diff the commit history?



The merge into master will be a commit. But as long as you do not push the changes to a remote (e.g. 'origin') you can always reset the merge using git reset HEAD~2 to abandon the merge commits.



One additional note, the 'HEAD~2' is an example of the number of commits to reset back to in the commit history. If your merge commit put you 'x' number of commits ahead of your remote you would replace the '2' with the number of commits a git status reports you are ahead of your remote.






share|improve this answer
























  • Thanks, but I have the habit of checking diffs before committing, to verify. If I merge onto master, and then make changes, the diff for the pending changes will be relative to after the merge, but I want them after the master. So let's not pursue your suggested approach. It's also too convoluted. Is there a single command to run that does what I originally asked -- take all the commits to the branch and apply them on master as pending changes. My git knowledge is basic, so I want to keep things simple.

    – Vaddadi Kartick
    Jan 3 at 7:24











  • I thought it would be a good way to increase your git skills by using Git's feature of undoing commits (ones not pushed to an origin). But I understand your perspective and agree it's more convoluted than you were probably looking for. I did not know a simpler way... but I'm sure there is one.

    – benhorgen
    Jan 3 at 20:36



















1














I'm sure there is a number of valid ways to do this. I'd like to describe a short one using patches to transfer your code changes from the feature branch.



cd $the-root-of-your-project
git checkout feature-branch
git format-patch <the-commit-since-you-began-the-feature>


This will create one patch file per commit. (Hint: The commit you need to enter in the last command is the one before the first one you want to transfer. See since and revision range in https://git-scm.com/docs/git-format-patch for details.)



Secondly, I suggest you cat all that *.patch files into one.



Thirdly, get the changes of that accumulated patch file into the index of master:



git checkout master
patch -p1 < accumulated.patch
git diff
git add .
...


patch is the one from bash and -p1 is necessary to strip the git-specific path prefix in the patch file off.






share|improve this answer
























  • Thanks. The two branches that have diverged a bit. Can this be taken care of when applying the patch, or is it simpler to first merge changes from master into the branch, and then generate the patch file?

    – Vaddadi Kartick
    Jan 3 at 15:13






  • 1





    You have found a disadvantage of this approach, since applying the patch is basically a 2-way merge, hence it does not take the common history of master and branch into account. I.e. every merge conflict needs your attention. So yes, it will be beneficial to merge master into branch first.

    – salchint
    Jan 5 at 12:33












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54015570%2fhow-do-you-move-committed-changes-from-a-branch-to-master-as-pending-changes%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














First, I'll give the commands, then what they are really doing and why this achieves what you want. I assume below that the feature branch is just called branch—change the name given to git merge if it has some other name.



git status               # and make sure everything is committed on your branch
# do any extra commits here if required

git checkout master # change the current branch/commit, index, and work-tree
git merge --squash --no-commit branch


(In git merge, --squash implies --no-commit anyway, so you can omit the second flag argument here. I included it more for illustration. Moreover, --squash means do the merging action in the index and work-tree, but don't make a merge commit.)



You may, depending on your tools, want to do git reset (which defaults to a --mixed reset with HEAD as the commit) to copy the HEAD commit back into the index, so that plain git diff shows you everything, and git status shows everything as not staged for commit.



Long



It's important to note, here, that there isn't really such a thing as pending changes. Git doesn't store changes at all. What Git stores are commits, and each commit is a complete snapshot of all files. When you ask Git what changed, you must tell Git about two commits, or at the least, two trees-full-of-files. Git then figures out, from those two inputs, what's different in snapshots A and B. Then Git tells you those differences—but A and B remain full snapshots. In some ways, none of this matters—you see changes when you want, and snapshots when you want. But if your mental model matches what Git really does, you'll have fewer mysteries to solve: your own job will be easier. The most important way this matters is to remember: In order to see changes or differences, you must provide two inputs. Sometimes, one of those inputs is implied. Sometimes, both of them are implied!



This last is the case with a simple git diff or git diff --cached / git diff --staged: Git compares the index to the work-tree (plain git diff), or the HEAD commit to the index (--staged or --cached). The option, if any, determines the two inputs. That is, Git takes two of the three things from this list:




  • the HEAD commit, which is a real commit, containing all files in the special Git-only, frozen/read-only form;

  • the index, which is essentially the proposed next commit, and contains a copy of all the files, also in the Git-only form but not quite frozen;

  • the work-tree, which has your files in their ordinary useful form.


With two of these things in hand, Git compares them and tells you what's different. The git status command runs, as part of its job, both of these two git diffs (with certain options always set, such as --name-status and --find-renames=50%) and summarizes the results: the output from git diff --staged are changes staged for commit and the output from git diff are changes not staged for commit.



You can also manually run git diff HEAD. This chooses HEAD and your work-tree as the two inputs: you explicitly named one of them, HEAD, in the arguments, and the other is implied. That compares the frozen HEAD contents to the unfrozen, normal-format, work-tree contents, and shows you the difference. Again, Git is comparing full snapshots: the second one is the live work-tree, snapshotted by the process of diffing.



(Aside: what you want to do, in my opinion, is probably the wrong way to go about it. You can often make your own job easier by committing early and often. Doing diffs is a good idea, but you can do them from base-commit to tip-commit, i.e., across a span of commits, to assess the overall result. You can then use a interactive rebase, or—my preferred method—additional branches, to reconstruct the smaller commits into a more sensible series of commits. But much of this is personal preference. It sounds like your Xcode tool could work a lot better than it is doing; the way you're using it is not wrong, it's just terribly limiting.)



How and why this works



I started writing a longer post but it got out of hand, so I'll just say: see some of my other StackOverflow answers for how Git makes commits out of the index, not the work-tree, and how these commits update the branch name to which HEAD is attached.



Git's merge is itself also a pretty big topic. However, we can say that merging uses the index to achieve its merge result, with the work-tree playing a secondary role, mainly for the case where there are merge conflicts.



A real merge—that is, a git merge that does a full three-way merge and will, in the end, make a new commit of type merge commit—makes its new commit with two parents. These two parents are two of the three inputs that went into computing the merge result. The third input is implied by the other two; it's the merge base. Git finds the merge base on its own, using the commit graph. Git then compares the merge base to the --ours and --theirs branch tips, as if using two git diff --find-renames commands: one from base to ours, one from base to theirs.



Ignoring issues like added, deleted, or renamed files, the comparison of these three commits produces a list of who changed which files. If we changed some file that they didn't change, or they changed some file that we didn't, merging these is easy: Git can just take our file, or their file. If neither of us changed the file at all, Git can take any of the three versions of the file (merge base, ours, or theirs).



For the difficult case—we both changed some file—Git takes the merge base to start with, and combines our changes and their changes and applies the combined changes to the merge-base copy. If our changes and their changes touch different lines, the combining is straightforward and Git declares the result a success (even if it makes no sense in reality). If we and they both changed the same lines, Git declares a merge conflict.



The merge conflict case is the messiest. Here, Git leaves all three input files in the index, and writes the conflicted merge to the work-tree. Your job, as the human running git merge, is to come up with the correct merge, however you like. You can use the three index copies of the file, or the work-tree copy, or all of these. You resolve the merge yourself and then use git add to write the correct result into the index, replacing the three unmerged copies with a single merged copy. That resolves this conflict; once you have resolved all conflicts, you can finish the merge.



If you run git merge with --no-commit, Git will do as much merging as it can on its own—which might be all of it—and then stop, the same way it would for a merge conflict. If there were no conflicts, this leaves both the index and work-tree in a ready-to-commit state. (If there were conflicts, the --no-commit option has no effect: Git was already going to stop, with the mess left behind, and still stops, with the mess left behind for you to fix.)



In all of these cases, though, Git leaves behind a file in the .git directory, telling Git that the next commit—whether from git merge --continue or git commit—should have two parents. That makes the new commit a merge commit, which will tie together the two branches:



             I--J   [master pointed to J when we started]
/
...--F--G--H M <-- master (HEAD)
/
K--L <-- branch


That's not what you want. So, we use git merge --squash, which tells Git: Do the merge work as usual, but instead of making a merge commit, arrange for the next commit to be an ordinary commit. That is, if Git were to make a new commit M, it would look like this:



             I--J--M   <-- master (HEAD)
/
...--F--G--H

K--L <-- branch


For no particularly good reason, --squash inhibits the commit even if the merge goes well. So after git merge --squash, the index and work-tree are updated, but you can make more changes to the work-tree, use git add to copy the updated files into the index, and only when you are done, use git commit to make the new commit.



(For a more trivial merge, where Git would default to doing a fast-forward, --squash inhibits the fast-forward mode as well, as if by git merge --no-ff. So --squash, without --no-ff and without --no-commit, suffices.)



The final git reset, if used and needed, just copies the HEAD commit back into the index. That is, you probably want your tool to compare the HEAD commit to the work-tree, as if you were running git diff HEAD. If the tool compares the index to the work-tree instead, you can get the same effect by de-updating the index to match HEAD, after the --squash operation updated it.






share|improve this answer
























  • I upvoted this. Also thanks so much for the effort to help a stranger!

    – Vaddadi Kartick
    Jan 4 at 4:27
















3














First, I'll give the commands, then what they are really doing and why this achieves what you want. I assume below that the feature branch is just called branch—change the name given to git merge if it has some other name.



git status               # and make sure everything is committed on your branch
# do any extra commits here if required

git checkout master # change the current branch/commit, index, and work-tree
git merge --squash --no-commit branch


(In git merge, --squash implies --no-commit anyway, so you can omit the second flag argument here. I included it more for illustration. Moreover, --squash means do the merging action in the index and work-tree, but don't make a merge commit.)



You may, depending on your tools, want to do git reset (which defaults to a --mixed reset with HEAD as the commit) to copy the HEAD commit back into the index, so that plain git diff shows you everything, and git status shows everything as not staged for commit.



Long



It's important to note, here, that there isn't really such a thing as pending changes. Git doesn't store changes at all. What Git stores are commits, and each commit is a complete snapshot of all files. When you ask Git what changed, you must tell Git about two commits, or at the least, two trees-full-of-files. Git then figures out, from those two inputs, what's different in snapshots A and B. Then Git tells you those differences—but A and B remain full snapshots. In some ways, none of this matters—you see changes when you want, and snapshots when you want. But if your mental model matches what Git really does, you'll have fewer mysteries to solve: your own job will be easier. The most important way this matters is to remember: In order to see changes or differences, you must provide two inputs. Sometimes, one of those inputs is implied. Sometimes, both of them are implied!



This last is the case with a simple git diff or git diff --cached / git diff --staged: Git compares the index to the work-tree (plain git diff), or the HEAD commit to the index (--staged or --cached). The option, if any, determines the two inputs. That is, Git takes two of the three things from this list:




  • the HEAD commit, which is a real commit, containing all files in the special Git-only, frozen/read-only form;

  • the index, which is essentially the proposed next commit, and contains a copy of all the files, also in the Git-only form but not quite frozen;

  • the work-tree, which has your files in their ordinary useful form.


With two of these things in hand, Git compares them and tells you what's different. The git status command runs, as part of its job, both of these two git diffs (with certain options always set, such as --name-status and --find-renames=50%) and summarizes the results: the output from git diff --staged are changes staged for commit and the output from git diff are changes not staged for commit.



You can also manually run git diff HEAD. This chooses HEAD and your work-tree as the two inputs: you explicitly named one of them, HEAD, in the arguments, and the other is implied. That compares the frozen HEAD contents to the unfrozen, normal-format, work-tree contents, and shows you the difference. Again, Git is comparing full snapshots: the second one is the live work-tree, snapshotted by the process of diffing.



(Aside: what you want to do, in my opinion, is probably the wrong way to go about it. You can often make your own job easier by committing early and often. Doing diffs is a good idea, but you can do them from base-commit to tip-commit, i.e., across a span of commits, to assess the overall result. You can then use a interactive rebase, or—my preferred method—additional branches, to reconstruct the smaller commits into a more sensible series of commits. But much of this is personal preference. It sounds like your Xcode tool could work a lot better than it is doing; the way you're using it is not wrong, it's just terribly limiting.)



How and why this works



I started writing a longer post but it got out of hand, so I'll just say: see some of my other StackOverflow answers for how Git makes commits out of the index, not the work-tree, and how these commits update the branch name to which HEAD is attached.



Git's merge is itself also a pretty big topic. However, we can say that merging uses the index to achieve its merge result, with the work-tree playing a secondary role, mainly for the case where there are merge conflicts.



A real merge—that is, a git merge that does a full three-way merge and will, in the end, make a new commit of type merge commit—makes its new commit with two parents. These two parents are two of the three inputs that went into computing the merge result. The third input is implied by the other two; it's the merge base. Git finds the merge base on its own, using the commit graph. Git then compares the merge base to the --ours and --theirs branch tips, as if using two git diff --find-renames commands: one from base to ours, one from base to theirs.



Ignoring issues like added, deleted, or renamed files, the comparison of these three commits produces a list of who changed which files. If we changed some file that they didn't change, or they changed some file that we didn't, merging these is easy: Git can just take our file, or their file. If neither of us changed the file at all, Git can take any of the three versions of the file (merge base, ours, or theirs).



For the difficult case—we both changed some file—Git takes the merge base to start with, and combines our changes and their changes and applies the combined changes to the merge-base copy. If our changes and their changes touch different lines, the combining is straightforward and Git declares the result a success (even if it makes no sense in reality). If we and they both changed the same lines, Git declares a merge conflict.



The merge conflict case is the messiest. Here, Git leaves all three input files in the index, and writes the conflicted merge to the work-tree. Your job, as the human running git merge, is to come up with the correct merge, however you like. You can use the three index copies of the file, or the work-tree copy, or all of these. You resolve the merge yourself and then use git add to write the correct result into the index, replacing the three unmerged copies with a single merged copy. That resolves this conflict; once you have resolved all conflicts, you can finish the merge.



If you run git merge with --no-commit, Git will do as much merging as it can on its own—which might be all of it—and then stop, the same way it would for a merge conflict. If there were no conflicts, this leaves both the index and work-tree in a ready-to-commit state. (If there were conflicts, the --no-commit option has no effect: Git was already going to stop, with the mess left behind, and still stops, with the mess left behind for you to fix.)



In all of these cases, though, Git leaves behind a file in the .git directory, telling Git that the next commit—whether from git merge --continue or git commit—should have two parents. That makes the new commit a merge commit, which will tie together the two branches:



             I--J   [master pointed to J when we started]
/
...--F--G--H M <-- master (HEAD)
/
K--L <-- branch


That's not what you want. So, we use git merge --squash, which tells Git: Do the merge work as usual, but instead of making a merge commit, arrange for the next commit to be an ordinary commit. That is, if Git were to make a new commit M, it would look like this:



             I--J--M   <-- master (HEAD)
/
...--F--G--H

K--L <-- branch


For no particularly good reason, --squash inhibits the commit even if the merge goes well. So after git merge --squash, the index and work-tree are updated, but you can make more changes to the work-tree, use git add to copy the updated files into the index, and only when you are done, use git commit to make the new commit.



(For a more trivial merge, where Git would default to doing a fast-forward, --squash inhibits the fast-forward mode as well, as if by git merge --no-ff. So --squash, without --no-ff and without --no-commit, suffices.)



The final git reset, if used and needed, just copies the HEAD commit back into the index. That is, you probably want your tool to compare the HEAD commit to the work-tree, as if you were running git diff HEAD. If the tool compares the index to the work-tree instead, you can get the same effect by de-updating the index to match HEAD, after the --squash operation updated it.






share|improve this answer
























  • I upvoted this. Also thanks so much for the effort to help a stranger!

    – Vaddadi Kartick
    Jan 4 at 4:27














3












3








3







First, I'll give the commands, then what they are really doing and why this achieves what you want. I assume below that the feature branch is just called branch—change the name given to git merge if it has some other name.



git status               # and make sure everything is committed on your branch
# do any extra commits here if required

git checkout master # change the current branch/commit, index, and work-tree
git merge --squash --no-commit branch


(In git merge, --squash implies --no-commit anyway, so you can omit the second flag argument here. I included it more for illustration. Moreover, --squash means do the merging action in the index and work-tree, but don't make a merge commit.)



You may, depending on your tools, want to do git reset (which defaults to a --mixed reset with HEAD as the commit) to copy the HEAD commit back into the index, so that plain git diff shows you everything, and git status shows everything as not staged for commit.



Long



It's important to note, here, that there isn't really such a thing as pending changes. Git doesn't store changes at all. What Git stores are commits, and each commit is a complete snapshot of all files. When you ask Git what changed, you must tell Git about two commits, or at the least, two trees-full-of-files. Git then figures out, from those two inputs, what's different in snapshots A and B. Then Git tells you those differences—but A and B remain full snapshots. In some ways, none of this matters—you see changes when you want, and snapshots when you want. But if your mental model matches what Git really does, you'll have fewer mysteries to solve: your own job will be easier. The most important way this matters is to remember: In order to see changes or differences, you must provide two inputs. Sometimes, one of those inputs is implied. Sometimes, both of them are implied!



This last is the case with a simple git diff or git diff --cached / git diff --staged: Git compares the index to the work-tree (plain git diff), or the HEAD commit to the index (--staged or --cached). The option, if any, determines the two inputs. That is, Git takes two of the three things from this list:




  • the HEAD commit, which is a real commit, containing all files in the special Git-only, frozen/read-only form;

  • the index, which is essentially the proposed next commit, and contains a copy of all the files, also in the Git-only form but not quite frozen;

  • the work-tree, which has your files in their ordinary useful form.


With two of these things in hand, Git compares them and tells you what's different. The git status command runs, as part of its job, both of these two git diffs (with certain options always set, such as --name-status and --find-renames=50%) and summarizes the results: the output from git diff --staged are changes staged for commit and the output from git diff are changes not staged for commit.



You can also manually run git diff HEAD. This chooses HEAD and your work-tree as the two inputs: you explicitly named one of them, HEAD, in the arguments, and the other is implied. That compares the frozen HEAD contents to the unfrozen, normal-format, work-tree contents, and shows you the difference. Again, Git is comparing full snapshots: the second one is the live work-tree, snapshotted by the process of diffing.



(Aside: what you want to do, in my opinion, is probably the wrong way to go about it. You can often make your own job easier by committing early and often. Doing diffs is a good idea, but you can do them from base-commit to tip-commit, i.e., across a span of commits, to assess the overall result. You can then use a interactive rebase, or—my preferred method—additional branches, to reconstruct the smaller commits into a more sensible series of commits. But much of this is personal preference. It sounds like your Xcode tool could work a lot better than it is doing; the way you're using it is not wrong, it's just terribly limiting.)



How and why this works



I started writing a longer post but it got out of hand, so I'll just say: see some of my other StackOverflow answers for how Git makes commits out of the index, not the work-tree, and how these commits update the branch name to which HEAD is attached.



Git's merge is itself also a pretty big topic. However, we can say that merging uses the index to achieve its merge result, with the work-tree playing a secondary role, mainly for the case where there are merge conflicts.



A real merge—that is, a git merge that does a full three-way merge and will, in the end, make a new commit of type merge commit—makes its new commit with two parents. These two parents are two of the three inputs that went into computing the merge result. The third input is implied by the other two; it's the merge base. Git finds the merge base on its own, using the commit graph. Git then compares the merge base to the --ours and --theirs branch tips, as if using two git diff --find-renames commands: one from base to ours, one from base to theirs.



Ignoring issues like added, deleted, or renamed files, the comparison of these three commits produces a list of who changed which files. If we changed some file that they didn't change, or they changed some file that we didn't, merging these is easy: Git can just take our file, or their file. If neither of us changed the file at all, Git can take any of the three versions of the file (merge base, ours, or theirs).



For the difficult case—we both changed some file—Git takes the merge base to start with, and combines our changes and their changes and applies the combined changes to the merge-base copy. If our changes and their changes touch different lines, the combining is straightforward and Git declares the result a success (even if it makes no sense in reality). If we and they both changed the same lines, Git declares a merge conflict.



The merge conflict case is the messiest. Here, Git leaves all three input files in the index, and writes the conflicted merge to the work-tree. Your job, as the human running git merge, is to come up with the correct merge, however you like. You can use the three index copies of the file, or the work-tree copy, or all of these. You resolve the merge yourself and then use git add to write the correct result into the index, replacing the three unmerged copies with a single merged copy. That resolves this conflict; once you have resolved all conflicts, you can finish the merge.



If you run git merge with --no-commit, Git will do as much merging as it can on its own—which might be all of it—and then stop, the same way it would for a merge conflict. If there were no conflicts, this leaves both the index and work-tree in a ready-to-commit state. (If there were conflicts, the --no-commit option has no effect: Git was already going to stop, with the mess left behind, and still stops, with the mess left behind for you to fix.)



In all of these cases, though, Git leaves behind a file in the .git directory, telling Git that the next commit—whether from git merge --continue or git commit—should have two parents. That makes the new commit a merge commit, which will tie together the two branches:



             I--J   [master pointed to J when we started]
/
...--F--G--H M <-- master (HEAD)
/
K--L <-- branch


That's not what you want. So, we use git merge --squash, which tells Git: Do the merge work as usual, but instead of making a merge commit, arrange for the next commit to be an ordinary commit. That is, if Git were to make a new commit M, it would look like this:



             I--J--M   <-- master (HEAD)
/
...--F--G--H

K--L <-- branch


For no particularly good reason, --squash inhibits the commit even if the merge goes well. So after git merge --squash, the index and work-tree are updated, but you can make more changes to the work-tree, use git add to copy the updated files into the index, and only when you are done, use git commit to make the new commit.



(For a more trivial merge, where Git would default to doing a fast-forward, --squash inhibits the fast-forward mode as well, as if by git merge --no-ff. So --squash, without --no-ff and without --no-commit, suffices.)



The final git reset, if used and needed, just copies the HEAD commit back into the index. That is, you probably want your tool to compare the HEAD commit to the work-tree, as if you were running git diff HEAD. If the tool compares the index to the work-tree instead, you can get the same effect by de-updating the index to match HEAD, after the --squash operation updated it.






share|improve this answer













First, I'll give the commands, then what they are really doing and why this achieves what you want. I assume below that the feature branch is just called branch—change the name given to git merge if it has some other name.



git status               # and make sure everything is committed on your branch
# do any extra commits here if required

git checkout master # change the current branch/commit, index, and work-tree
git merge --squash --no-commit branch


(In git merge, --squash implies --no-commit anyway, so you can omit the second flag argument here. I included it more for illustration. Moreover, --squash means do the merging action in the index and work-tree, but don't make a merge commit.)



You may, depending on your tools, want to do git reset (which defaults to a --mixed reset with HEAD as the commit) to copy the HEAD commit back into the index, so that plain git diff shows you everything, and git status shows everything as not staged for commit.



Long



It's important to note, here, that there isn't really such a thing as pending changes. Git doesn't store changes at all. What Git stores are commits, and each commit is a complete snapshot of all files. When you ask Git what changed, you must tell Git about two commits, or at the least, two trees-full-of-files. Git then figures out, from those two inputs, what's different in snapshots A and B. Then Git tells you those differences—but A and B remain full snapshots. In some ways, none of this matters—you see changes when you want, and snapshots when you want. But if your mental model matches what Git really does, you'll have fewer mysteries to solve: your own job will be easier. The most important way this matters is to remember: In order to see changes or differences, you must provide two inputs. Sometimes, one of those inputs is implied. Sometimes, both of them are implied!



This last is the case with a simple git diff or git diff --cached / git diff --staged: Git compares the index to the work-tree (plain git diff), or the HEAD commit to the index (--staged or --cached). The option, if any, determines the two inputs. That is, Git takes two of the three things from this list:




  • the HEAD commit, which is a real commit, containing all files in the special Git-only, frozen/read-only form;

  • the index, which is essentially the proposed next commit, and contains a copy of all the files, also in the Git-only form but not quite frozen;

  • the work-tree, which has your files in their ordinary useful form.


With two of these things in hand, Git compares them and tells you what's different. The git status command runs, as part of its job, both of these two git diffs (with certain options always set, such as --name-status and --find-renames=50%) and summarizes the results: the output from git diff --staged are changes staged for commit and the output from git diff are changes not staged for commit.



You can also manually run git diff HEAD. This chooses HEAD and your work-tree as the two inputs: you explicitly named one of them, HEAD, in the arguments, and the other is implied. That compares the frozen HEAD contents to the unfrozen, normal-format, work-tree contents, and shows you the difference. Again, Git is comparing full snapshots: the second one is the live work-tree, snapshotted by the process of diffing.



(Aside: what you want to do, in my opinion, is probably the wrong way to go about it. You can often make your own job easier by committing early and often. Doing diffs is a good idea, but you can do them from base-commit to tip-commit, i.e., across a span of commits, to assess the overall result. You can then use a interactive rebase, or—my preferred method—additional branches, to reconstruct the smaller commits into a more sensible series of commits. But much of this is personal preference. It sounds like your Xcode tool could work a lot better than it is doing; the way you're using it is not wrong, it's just terribly limiting.)



How and why this works



I started writing a longer post but it got out of hand, so I'll just say: see some of my other StackOverflow answers for how Git makes commits out of the index, not the work-tree, and how these commits update the branch name to which HEAD is attached.



Git's merge is itself also a pretty big topic. However, we can say that merging uses the index to achieve its merge result, with the work-tree playing a secondary role, mainly for the case where there are merge conflicts.



A real merge—that is, a git merge that does a full three-way merge and will, in the end, make a new commit of type merge commit—makes its new commit with two parents. These two parents are two of the three inputs that went into computing the merge result. The third input is implied by the other two; it's the merge base. Git finds the merge base on its own, using the commit graph. Git then compares the merge base to the --ours and --theirs branch tips, as if using two git diff --find-renames commands: one from base to ours, one from base to theirs.



Ignoring issues like added, deleted, or renamed files, the comparison of these three commits produces a list of who changed which files. If we changed some file that they didn't change, or they changed some file that we didn't, merging these is easy: Git can just take our file, or their file. If neither of us changed the file at all, Git can take any of the three versions of the file (merge base, ours, or theirs).



For the difficult case—we both changed some file—Git takes the merge base to start with, and combines our changes and their changes and applies the combined changes to the merge-base copy. If our changes and their changes touch different lines, the combining is straightforward and Git declares the result a success (even if it makes no sense in reality). If we and they both changed the same lines, Git declares a merge conflict.



The merge conflict case is the messiest. Here, Git leaves all three input files in the index, and writes the conflicted merge to the work-tree. Your job, as the human running git merge, is to come up with the correct merge, however you like. You can use the three index copies of the file, or the work-tree copy, or all of these. You resolve the merge yourself and then use git add to write the correct result into the index, replacing the three unmerged copies with a single merged copy. That resolves this conflict; once you have resolved all conflicts, you can finish the merge.



If you run git merge with --no-commit, Git will do as much merging as it can on its own—which might be all of it—and then stop, the same way it would for a merge conflict. If there were no conflicts, this leaves both the index and work-tree in a ready-to-commit state. (If there were conflicts, the --no-commit option has no effect: Git was already going to stop, with the mess left behind, and still stops, with the mess left behind for you to fix.)



In all of these cases, though, Git leaves behind a file in the .git directory, telling Git that the next commit—whether from git merge --continue or git commit—should have two parents. That makes the new commit a merge commit, which will tie together the two branches:



             I--J   [master pointed to J when we started]
/
...--F--G--H M <-- master (HEAD)
/
K--L <-- branch


That's not what you want. So, we use git merge --squash, which tells Git: Do the merge work as usual, but instead of making a merge commit, arrange for the next commit to be an ordinary commit. That is, if Git were to make a new commit M, it would look like this:



             I--J--M   <-- master (HEAD)
/
...--F--G--H

K--L <-- branch


For no particularly good reason, --squash inhibits the commit even if the merge goes well. So after git merge --squash, the index and work-tree are updated, but you can make more changes to the work-tree, use git add to copy the updated files into the index, and only when you are done, use git commit to make the new commit.



(For a more trivial merge, where Git would default to doing a fast-forward, --squash inhibits the fast-forward mode as well, as if by git merge --no-ff. So --squash, without --no-ff and without --no-commit, suffices.)



The final git reset, if used and needed, just copies the HEAD commit back into the index. That is, you probably want your tool to compare the HEAD commit to the work-tree, as if you were running git diff HEAD. If the tool compares the index to the work-tree instead, you can get the same effect by de-updating the index to match HEAD, after the --squash operation updated it.







share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 3 at 11:38









torektorek

199k18247329




199k18247329













  • I upvoted this. Also thanks so much for the effort to help a stranger!

    – Vaddadi Kartick
    Jan 4 at 4:27



















  • I upvoted this. Also thanks so much for the effort to help a stranger!

    – Vaddadi Kartick
    Jan 4 at 4:27

















I upvoted this. Also thanks so much for the effort to help a stranger!

– Vaddadi Kartick
Jan 4 at 4:27





I upvoted this. Also thanks so much for the effort to help a stranger!

– Vaddadi Kartick
Jan 4 at 4:27













1














Have you considered doing a merge into master and then using your preferred diff tool to diff the commit history?



The merge into master will be a commit. But as long as you do not push the changes to a remote (e.g. 'origin') you can always reset the merge using git reset HEAD~2 to abandon the merge commits.



One additional note, the 'HEAD~2' is an example of the number of commits to reset back to in the commit history. If your merge commit put you 'x' number of commits ahead of your remote you would replace the '2' with the number of commits a git status reports you are ahead of your remote.






share|improve this answer
























  • Thanks, but I have the habit of checking diffs before committing, to verify. If I merge onto master, and then make changes, the diff for the pending changes will be relative to after the merge, but I want them after the master. So let's not pursue your suggested approach. It's also too convoluted. Is there a single command to run that does what I originally asked -- take all the commits to the branch and apply them on master as pending changes. My git knowledge is basic, so I want to keep things simple.

    – Vaddadi Kartick
    Jan 3 at 7:24











  • I thought it would be a good way to increase your git skills by using Git's feature of undoing commits (ones not pushed to an origin). But I understand your perspective and agree it's more convoluted than you were probably looking for. I did not know a simpler way... but I'm sure there is one.

    – benhorgen
    Jan 3 at 20:36
















1














Have you considered doing a merge into master and then using your preferred diff tool to diff the commit history?



The merge into master will be a commit. But as long as you do not push the changes to a remote (e.g. 'origin') you can always reset the merge using git reset HEAD~2 to abandon the merge commits.



One additional note, the 'HEAD~2' is an example of the number of commits to reset back to in the commit history. If your merge commit put you 'x' number of commits ahead of your remote you would replace the '2' with the number of commits a git status reports you are ahead of your remote.






share|improve this answer
























  • Thanks, but I have the habit of checking diffs before committing, to verify. If I merge onto master, and then make changes, the diff for the pending changes will be relative to after the merge, but I want them after the master. So let's not pursue your suggested approach. It's also too convoluted. Is there a single command to run that does what I originally asked -- take all the commits to the branch and apply them on master as pending changes. My git knowledge is basic, so I want to keep things simple.

    – Vaddadi Kartick
    Jan 3 at 7:24











  • I thought it would be a good way to increase your git skills by using Git's feature of undoing commits (ones not pushed to an origin). But I understand your perspective and agree it's more convoluted than you were probably looking for. I did not know a simpler way... but I'm sure there is one.

    – benhorgen
    Jan 3 at 20:36














1












1








1







Have you considered doing a merge into master and then using your preferred diff tool to diff the commit history?



The merge into master will be a commit. But as long as you do not push the changes to a remote (e.g. 'origin') you can always reset the merge using git reset HEAD~2 to abandon the merge commits.



One additional note, the 'HEAD~2' is an example of the number of commits to reset back to in the commit history. If your merge commit put you 'x' number of commits ahead of your remote you would replace the '2' with the number of commits a git status reports you are ahead of your remote.






share|improve this answer













Have you considered doing a merge into master and then using your preferred diff tool to diff the commit history?



The merge into master will be a commit. But as long as you do not push the changes to a remote (e.g. 'origin') you can always reset the merge using git reset HEAD~2 to abandon the merge commits.



One additional note, the 'HEAD~2' is an example of the number of commits to reset back to in the commit history. If your merge commit put you 'x' number of commits ahead of your remote you would replace the '2' with the number of commits a git status reports you are ahead of your remote.







share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 3 at 5:28









benhorgenbenhorgen

1,1771926




1,1771926













  • Thanks, but I have the habit of checking diffs before committing, to verify. If I merge onto master, and then make changes, the diff for the pending changes will be relative to after the merge, but I want them after the master. So let's not pursue your suggested approach. It's also too convoluted. Is there a single command to run that does what I originally asked -- take all the commits to the branch and apply them on master as pending changes. My git knowledge is basic, so I want to keep things simple.

    – Vaddadi Kartick
    Jan 3 at 7:24











  • I thought it would be a good way to increase your git skills by using Git's feature of undoing commits (ones not pushed to an origin). But I understand your perspective and agree it's more convoluted than you were probably looking for. I did not know a simpler way... but I'm sure there is one.

    – benhorgen
    Jan 3 at 20:36



















  • Thanks, but I have the habit of checking diffs before committing, to verify. If I merge onto master, and then make changes, the diff for the pending changes will be relative to after the merge, but I want them after the master. So let's not pursue your suggested approach. It's also too convoluted. Is there a single command to run that does what I originally asked -- take all the commits to the branch and apply them on master as pending changes. My git knowledge is basic, so I want to keep things simple.

    – Vaddadi Kartick
    Jan 3 at 7:24











  • I thought it would be a good way to increase your git skills by using Git's feature of undoing commits (ones not pushed to an origin). But I understand your perspective and agree it's more convoluted than you were probably looking for. I did not know a simpler way... but I'm sure there is one.

    – benhorgen
    Jan 3 at 20:36

















Thanks, but I have the habit of checking diffs before committing, to verify. If I merge onto master, and then make changes, the diff for the pending changes will be relative to after the merge, but I want them after the master. So let's not pursue your suggested approach. It's also too convoluted. Is there a single command to run that does what I originally asked -- take all the commits to the branch and apply them on master as pending changes. My git knowledge is basic, so I want to keep things simple.

– Vaddadi Kartick
Jan 3 at 7:24





Thanks, but I have the habit of checking diffs before committing, to verify. If I merge onto master, and then make changes, the diff for the pending changes will be relative to after the merge, but I want them after the master. So let's not pursue your suggested approach. It's also too convoluted. Is there a single command to run that does what I originally asked -- take all the commits to the branch and apply them on master as pending changes. My git knowledge is basic, so I want to keep things simple.

– Vaddadi Kartick
Jan 3 at 7:24













I thought it would be a good way to increase your git skills by using Git's feature of undoing commits (ones not pushed to an origin). But I understand your perspective and agree it's more convoluted than you were probably looking for. I did not know a simpler way... but I'm sure there is one.

– benhorgen
Jan 3 at 20:36





I thought it would be a good way to increase your git skills by using Git's feature of undoing commits (ones not pushed to an origin). But I understand your perspective and agree it's more convoluted than you were probably looking for. I did not know a simpler way... but I'm sure there is one.

– benhorgen
Jan 3 at 20:36











1














I'm sure there is a number of valid ways to do this. I'd like to describe a short one using patches to transfer your code changes from the feature branch.



cd $the-root-of-your-project
git checkout feature-branch
git format-patch <the-commit-since-you-began-the-feature>


This will create one patch file per commit. (Hint: The commit you need to enter in the last command is the one before the first one you want to transfer. See since and revision range in https://git-scm.com/docs/git-format-patch for details.)



Secondly, I suggest you cat all that *.patch files into one.



Thirdly, get the changes of that accumulated patch file into the index of master:



git checkout master
patch -p1 < accumulated.patch
git diff
git add .
...


patch is the one from bash and -p1 is necessary to strip the git-specific path prefix in the patch file off.






share|improve this answer
























  • Thanks. The two branches that have diverged a bit. Can this be taken care of when applying the patch, or is it simpler to first merge changes from master into the branch, and then generate the patch file?

    – Vaddadi Kartick
    Jan 3 at 15:13






  • 1





    You have found a disadvantage of this approach, since applying the patch is basically a 2-way merge, hence it does not take the common history of master and branch into account. I.e. every merge conflict needs your attention. So yes, it will be beneficial to merge master into branch first.

    – salchint
    Jan 5 at 12:33
















1














I'm sure there is a number of valid ways to do this. I'd like to describe a short one using patches to transfer your code changes from the feature branch.



cd $the-root-of-your-project
git checkout feature-branch
git format-patch <the-commit-since-you-began-the-feature>


This will create one patch file per commit. (Hint: The commit you need to enter in the last command is the one before the first one you want to transfer. See since and revision range in https://git-scm.com/docs/git-format-patch for details.)



Secondly, I suggest you cat all that *.patch files into one.



Thirdly, get the changes of that accumulated patch file into the index of master:



git checkout master
patch -p1 < accumulated.patch
git diff
git add .
...


patch is the one from bash and -p1 is necessary to strip the git-specific path prefix in the patch file off.






share|improve this answer
























  • Thanks. The two branches that have diverged a bit. Can this be taken care of when applying the patch, or is it simpler to first merge changes from master into the branch, and then generate the patch file?

    – Vaddadi Kartick
    Jan 3 at 15:13






  • 1





    You have found a disadvantage of this approach, since applying the patch is basically a 2-way merge, hence it does not take the common history of master and branch into account. I.e. every merge conflict needs your attention. So yes, it will be beneficial to merge master into branch first.

    – salchint
    Jan 5 at 12:33














1












1








1







I'm sure there is a number of valid ways to do this. I'd like to describe a short one using patches to transfer your code changes from the feature branch.



cd $the-root-of-your-project
git checkout feature-branch
git format-patch <the-commit-since-you-began-the-feature>


This will create one patch file per commit. (Hint: The commit you need to enter in the last command is the one before the first one you want to transfer. See since and revision range in https://git-scm.com/docs/git-format-patch for details.)



Secondly, I suggest you cat all that *.patch files into one.



Thirdly, get the changes of that accumulated patch file into the index of master:



git checkout master
patch -p1 < accumulated.patch
git diff
git add .
...


patch is the one from bash and -p1 is necessary to strip the git-specific path prefix in the patch file off.






share|improve this answer













I'm sure there is a number of valid ways to do this. I'd like to describe a short one using patches to transfer your code changes from the feature branch.



cd $the-root-of-your-project
git checkout feature-branch
git format-patch <the-commit-since-you-began-the-feature>


This will create one patch file per commit. (Hint: The commit you need to enter in the last command is the one before the first one you want to transfer. See since and revision range in https://git-scm.com/docs/git-format-patch for details.)



Secondly, I suggest you cat all that *.patch files into one.



Thirdly, get the changes of that accumulated patch file into the index of master:



git checkout master
patch -p1 < accumulated.patch
git diff
git add .
...


patch is the one from bash and -p1 is necessary to strip the git-specific path prefix in the patch file off.







share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 3 at 11:59









salchintsalchint

1645




1645













  • Thanks. The two branches that have diverged a bit. Can this be taken care of when applying the patch, or is it simpler to first merge changes from master into the branch, and then generate the patch file?

    – Vaddadi Kartick
    Jan 3 at 15:13






  • 1





    You have found a disadvantage of this approach, since applying the patch is basically a 2-way merge, hence it does not take the common history of master and branch into account. I.e. every merge conflict needs your attention. So yes, it will be beneficial to merge master into branch first.

    – salchint
    Jan 5 at 12:33



















  • Thanks. The two branches that have diverged a bit. Can this be taken care of when applying the patch, or is it simpler to first merge changes from master into the branch, and then generate the patch file?

    – Vaddadi Kartick
    Jan 3 at 15:13






  • 1





    You have found a disadvantage of this approach, since applying the patch is basically a 2-way merge, hence it does not take the common history of master and branch into account. I.e. every merge conflict needs your attention. So yes, it will be beneficial to merge master into branch first.

    – salchint
    Jan 5 at 12:33

















Thanks. The two branches that have diverged a bit. Can this be taken care of when applying the patch, or is it simpler to first merge changes from master into the branch, and then generate the patch file?

– Vaddadi Kartick
Jan 3 at 15:13





Thanks. The two branches that have diverged a bit. Can this be taken care of when applying the patch, or is it simpler to first merge changes from master into the branch, and then generate the patch file?

– Vaddadi Kartick
Jan 3 at 15:13




1




1





You have found a disadvantage of this approach, since applying the patch is basically a 2-way merge, hence it does not take the common history of master and branch into account. I.e. every merge conflict needs your attention. So yes, it will be beneficial to merge master into branch first.

– salchint
Jan 5 at 12:33





You have found a disadvantage of this approach, since applying the patch is basically a 2-way merge, hence it does not take the common history of master and branch into account. I.e. every merge conflict needs your attention. So yes, it will be beneficial to merge master into branch first.

– salchint
Jan 5 at 12:33


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54015570%2fhow-do-you-move-committed-changes-from-a-branch-to-master-as-pending-changes%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

ts Property 'filter' does not exist on type '{}'

mat-slide-toggle shouldn't change it's state when I click cancel in confirmation window