@Mark Longair nailed it in his answer here, but I'd like to add some additional insight.
Related, and answering the question of how to break up a large Pull Request (PR), especially when squashing your commits is impractical due to one or more merges of master into your feature_branch
My situation: I made a big feature_branch with 30 commits and opened a Pull Request (PR) on GitHub to merge it into master . Branch master changed a ton underneath me, and received 200 commits my feature_branch didn't have. To resolve conflicts I did git checkout feature_branch and git merge master to merge master 's changes into my feature_branch . I chose to merge rather than rebase onto latest master so I would have to resolve conflicts only one single time instead of potentially 30 times (once for each of my commits). I didn't want to squash my 30 commits into 1 first and then rebase onto the latest master because that might wipe away GitHub review comment history in the PR. So, I merged master into my feature branch and resolved conflicts 1 single time. All was well. My PR, however, was too big for my colleagues to review. I needed to split it up. I went to squash my 30 commits and OH NO! WHERE ARE THEY? THEY ARE ALL INTERMINGLED WITH master 's 200 recent commits now because I merged master into my feature_branch ! WHAT DO I DO?
git cherry usage in case you want to try to git cherry-pick individual commits:
git cherry to the rescue (sort of)! To see all the commits that are in feature_branch but NOT in master I can do:
git checkout feature_branch
git cherry master
OR, I can check commits from ANY branch withOUT ensuring I'm on feature_branch first by doing git cherry [upstream_branch] [feature_branch] , like this. Again, this checks to see which commits ARE in feature_branch but are NOT in upstream_branch ( master in this case):
git cherry master feature_branch
Adding -v also shows the commit message subject lines:
git cherry -v master
Piping to "word count" "-lines" ( wc -l ) counts how many commits there are:
git cherry master | wc -l
You can compare this count against the commit number shown in your GithHub PR to feel better about knowing git cherry really is working. You can also compare the git hashes one by one and see they match between git cherry and GitHub. Note that git cherry will NOT count any merge commits where you merged master into feature_branch , but GitHub WILL. So if you see a small discrepancy in the count, search the GitHub PR commit page for the word "merge" and you'll probably see that's the culprit which is not showing up in git cherry . Ex: a commit titled "Merge branch 'master' into feature_branch" will show up in the GitHub PR but not when you run git cherry master feature_branch . This is fine and expected. So, now I have a means of finding out which diffs I may want to cherry-pick onto a fresh feature branch to split up this diff: I can use git cherry master feature_branch locally, or look at the commits in the GitHub PR.
How squashing could help--if only we could squash:
An alternative, however, to split up my big diff is to squash all 30 of my commits into one, patch that onto a new feature branch, soft reset the patch commit, then use git gui to add pieces file by file, chunk by chunk, or line by line. Once I get one sub-feature, I can commit what I've added then check out a new branch, add some more, commit, check out a new branch, etc, until I have my big feature broken out into several sub-features. The problem is that my 30 commits are intermingled with the other 200 commits from other people due to my git merge master into my feature_branch , so rebasing is therefore impractical, as I'd have to sift through 230 commits to re-order and squash my 30 commits.
How to use a patch file as a much easier replacement for squashing:
A work-around is to simply obtain a patch file containing a "squash-equivalent" of all 30 of my commits, patch it onto a new fork of master (a new sub-feature-branch), and work from there, as follows:
git checkout feature_branch
# ensure I have the latest changes from master merged into feature_branch
git merge master
# Obtain a patch file, which is the equivalent of a squash of my 30 commits into 1 commit:
git diff master..feature_branch > ~/mypatch.patch
git checkout master
# Create a new, sub-feature branch
git checkout -b feature_branch2
# Patch the 30 commit patch file onto it:
git apply ~/mypatch.patch
Now I have my 30-commit patch all applied locally, but unstaged and uncommitted.
Now use git gui to add files, chunks, and/or lines and break up your big PR or "diff":
Note that if you don't have git gui , you can easily install it in Ubuntu with sudo apt install git-gui .*
I can now run git gui and start adding files, chunks, and/or lines (by right-clicking in the git GUI program), and break up the 30 commit feature branch into sub branches as described just above, repeatedly adding, committing, then forking a new feature branch and repeating this cycle until all changes have been added to a sub-feature-branch and my 30-commit feature is successfully broken up into 3 or 4 sub-features. I can open up a separate PR for each of these sub-features now, and they will be easier for my team to review.
References:
Create patch or diff file from git repository and apply it to another different git repository
关键词是--cherry-pick --cherry-pick 当提交集受到对称差的限制时,忽略任何引入了与“另一边”的另一个提交相同的修改的提交。例如,如果你有两个分支,A和B,通常的方法是用--left-right,就像上面的例子中描述的那个选项一样,但是它显示的是从另一个分支中挑选出来的提交(例如,“3rd on B”可能是从分支A中挑选出来的)。使用此选项,这样的提交对将被排除在输出之外。
6条答案
按热度按时间m4pnthwp1#
@Mark Longair nailed it in his answer here, but I'd like to add some additional insight.
Related, and answering the question of how to break up a large Pull Request (PR), especially when squashing your commits is impractical due to one or more merges of master into your feature_branch
My situation:
I made a big
feature_branch
with 30 commits and opened a Pull Request (PR) on GitHub to merge it intomaster
. Branchmaster
changed a ton underneath me, and received 200 commits myfeature_branch
didn't have. To resolve conflicts I didgit checkout feature_branch
andgit merge master
to mergemaster
's changes into myfeature_branch
. I chose tomerge
rather thanrebase
onto latest master so I would have to resolve conflicts only one single time instead of potentially 30 times (once for each of my commits). I didn't want to squash my 30 commits into 1 first and then rebase onto the latestmaster
because that might wipe away GitHub review comment history in the PR. So, I merged master into my feature branch and resolved conflicts 1 single time. All was well. My PR, however, was too big for my colleagues to review. I needed to split it up. I went to squash my 30 commits and OH NO! WHERE ARE THEY? THEY ARE ALL INTERMINGLED WITHmaster
's 200 recent commits now because I mergedmaster
into myfeature_branch
! WHAT DO I DO?git cherry
usage in case you want to try togit cherry-pick
individual commits:git cherry
to the rescue (sort of)!To see all the commits that are in
feature_branch
but NOT inmaster
I can do:OR, I can check commits from ANY branch withOUT ensuring I'm on
feature_branch
first by doinggit cherry [upstream_branch] [feature_branch]
, like this. Again, this checks to see which commits ARE infeature_branch
but are NOT inupstream_branch
(master
in this case):Adding
-v
also shows the commit message subject lines:Piping to "word count" "-lines" (
wc -l
) counts how many commits there are:You can compare this count against the commit number shown in your GithHub PR to feel better about knowing
git cherry
really is working. You can also compare the git hashes one by one and see they match betweengit cherry
and GitHub. Note thatgit cherry
will NOT count any merge commits where you mergedmaster
intofeature_branch
, but GitHub WILL. So if you see a small discrepancy in the count, search the GitHub PR commit page for the word "merge" and you'll probably see that's the culprit which is not showing up ingit cherry
. Ex: a commit titled "Merge branch 'master' into feature_branch" will show up in the GitHub PR but not when you rungit cherry master feature_branch
. This is fine and expected.So, now I have a means of finding out which diffs I may want to cherry-pick onto a fresh feature branch to split up this diff: I can use
git cherry master feature_branch
locally, or look at the commits in the GitHub PR.How squashing could help--if only we could squash:
An alternative, however, to split up my big diff is to squash all 30 of my commits into one, patch that onto a new feature branch, soft reset the patch commit, then use
git gui
to add pieces file by file, chunk by chunk, or line by line. Once I get one sub-feature, I can commit what I've added then check out a new branch, add some more, commit, check out a new branch, etc, until I have my big feature broken out into several sub-features. The problem is that my 30 commits are intermingled with the other 200 commits from other people due to mygit merge master
into myfeature_branch
, so rebasing is therefore impractical, as I'd have to sift through 230 commits to re-order and squash my 30 commits.How to use a patch file as a much easier replacement for squashing:
A work-around is to simply obtain a patch file containing a "squash-equivalent" of all 30 of my commits, patch it onto a new fork of
master
(a new sub-feature-branch), and work from there, as follows:Now I have my 30-commit patch all applied locally, but unstaged and uncommitted.
Now use
git gui
to add files, chunks, and/or lines and break up your big PR or "diff":git gui
, you can easily install it in Ubuntu withsudo apt install git-gui
.*I can now run
git gui
and start adding files, chunks, and/or lines (by right-clicking in the git GUI program), and break up the 30 commit feature branch into sub branches as described just above, repeatedly adding, committing, then forking a new feature branch and repeating this cycle until all changes have been added to a sub-feature-branch and my 30-commit feature is successfully broken up into 3 or 4 sub-features. I can open up a separate PR for each of these sub-features now, and they will be easier for my team to review.References:
egmofgnx2#
很少使用的命令
git cherry
(docs)向您显示尚未被挑选的提交。简而言之:
第一个
输出示例:
+
表示提交仅在next
中,但不在main
中-
表示提交是在两个分支中如果你希望提交没有主题行,请删除
-v
:qhhrdooz3#
同样,你可以用它来得到一个分支之间没有共享的 * 实际 * 不同提交的列表:
输出示例:
关键词是
--cherry-pick
--cherry-pick
当提交集受到对称差的限制时,忽略任何引入了与“另一边”的另一个提交相同的修改的提交。例如,如果你有两个分支,A和B,通常的方法是用--left-right,就像上面的例子中描述的那个选项一样,但是它显示的是从另一个分支中挑选出来的提交(例如,“3rd on B”可能是从分支A中挑选出来的)。使用此选项,这样的提交对将被排除在输出之外。
更新正如评论中提到的,最近的git版本增加了
--cherry-mark
:--cherry-mark
类似于--cherry-pick(见下文),但用=标记等价的提交,而不是省略它们,用+标记不等价的提交。
mefy6pfw4#
你可以尝试做git日志子集:
ijnw1ujt5#
不如
结果与Byran的答案类似(提交顺序不同),但我们的两个答案都会产生不同分支之间的提交,而不是只显示一个分支中的内容,而不显示另一个分支中的内容。
oxosxuxt6#
要获得没有集成到发布分支(next)的提交列表,你可以用途:
有关详细信息,请查看git-rev-list。