tl;dr: probably better to use git rebase -i
I don't guess I see what you expect to get out of tagging. To avoid saying
git cherry-pick commit
for each commit you would instead say
git tag my_tag commit
and then still have to actually run the script to copy the commits... it's more work than just doing it manually. (Plus, the above tag commands wouldn't work as you want, because a given tag points to exactly one object; so you'd have to use many tags, and have your cherry-pick script find all of them...)
That's not to say manual cherry-picking is the best way. The point of cherry-pick is to grab "that one change I need"; if you need to process an entire branch, it's probably easier to use git rebase
. The rebase
operation is often misunderstood; it copies commits, much like cherry-pick. (People often seem to think that it "replaces" commits, removing the originals; this is not exactly true. It can change the history of a ref, but that's the extent of that.)
So for example, if you start with
A -- B -- C -- D -- E -- F -- G -- H <--(main-branch)
you could
git checkout main-branch
git checkout -b release-branch
git rebase -i master~6
(I've used master~6
because it's an expression that refers to B
; B
's object ID (hash) would also work. I chose B
because C
is the first commit you don't want to retain - so rewriting starts after B
. If you wanted to remove A
, you could use an expression that resolves to A
's parent if A
has a parent, or use --root
if A
does not have a parent.)
Now git will open an editor and show you a "todo" list, with one line for each commit in your branch back to (but not including) B
. For the commits you want to remove, change the first word on that commit's line from pick
to drop
(or just delete the line).
When you exit the editor, the rebase operation will begin "copying" commits (i.e. making new commits that apply the same changes on the new base). At each step, there could be conflicts (if a change in a later commit depends on a change in an earlier commit you removed); you'll be prompted to resolve those and continue the rebase operation.
When it's done you will have
A -- B -- C -- D -- E -- F -- G -- H <--(main-branch)
\
D' -- F' -- G' <--(release-branch)
where D'
applies the same changes as D
, etc.
This is not without potential drawbacks (though the drawbacks are the same for rebase
as they would've been for cherry-pick
); it really depends what you'll do with the branches from here. If release-branch
is just a terminal state that you'll release and forget, it's probably fine. If you might need to hotfix the release, you'll find that merging between release-branch
and main-branch
could be difficult; so then you might have to use cherry-pick
or rebase
to share the fix between the release and your main development line.