0

I assume that this question looks almost like a few others, but I've tried around 7 approaches from answers like Delete last commit in bitbucket and How can I remove a commit on GitHub? , but unfortunately still didn't find the solution.

The situation: I wrote code in branch "exampleBranch", did around of 30 commits (with push) with diff in a lot of files (create new files, remove redundant, etc) so there are a quite lot of diff. On this step (say on commit with number 30) I did merge-request, and by some reasons continued to commit to this branch (but without pushing, so I have it only locally). Simultaneously another person have done the code review of the pushed 30 commits and asked me to divide the code in MR, and the code that was written after 30th commit.

So absolutely clear for me, that all my changes after 30th commit I'm able to get just by creating a new branch (say "anotherBranch") from the current local "exampleBranch". Is that true, right ?

But unclear point for me is how to remove (locally and remotely) all the commits after 30th (there are ~45+ additional commits) ? So finally in the branch should be only the data that is already cheked by reviewer.

If it's important we use gitlab.

Thanks in advance for your replies.

Kache
  • 15,647
  • 12
  • 51
  • 79
Ustin
  • 568
  • 6
  • 19

2 Answers2

2

It's a little difficult to understand your current Git history state. I'm going to make a couple assumptions (which I'll detail). Run git log --all --graph --oneline --decorate yourself to compare and correct my assumptions if needed.

It sounds like you have a situation like this:

* M1 <- origin/master (with exampleBranch merged)
|\
| | * C30_C74 <- exampleBranch (additional 45 local-only commits)
| |/
| * C0_C29 <- origin/exampleBranch (30 commits, pushed)
|/
* M0

Your local exampleBranch has 75 commits total on top of M0, the first 30 commits at C0_C29 have already been merged, and you've been asked to split the remaining 45 at C30_C74 into a separate independent merge.

There are two functionally identical ways to do this:

Rebase

Create anotherBranch where local exampleBranch is and rebase to "cut off" C30_C74 and "reattach" it to M1.

git checkout exampleBranch                              # move HEAD to C30_C74
git checkout -b anotherBranch                           # create anotherBranch at HEAD (C30_C74)
git rebase anotherBranch C0_C29 --onto origin/master    # rebase anotherBranch from C0_C29 to M1

Cherry-pick

Create anotherBranch at M1, and cherry-pick to "copy"/"replay" the C30_C74 commits in your local exampleBranch.

git checkout origin/master                              # move HEAD to M1
git checkout -b anotherBranch                           # create anotherBranch at HEAD (M1)
git cherry-pick C0_C29..C30_C74                         # cherry-pick the range C0_C29..C30_C74 to HEAD

Once you're done, you'll have something like this:

* D0_D44 <- anotherBranch (identical changes as C30_C74)
* M1 <- origin/master (with exampleBranch merged)
|\
| | * C30_C74 <- exampleBranch (additional 45 local-only commits)
| |/
| * C0_C29 <- origin/exampleBranch (30 commits, pushed)
|/
* M0

And you can treat anotherBranch like a fresh branch based off master and create a new merge request.

For a fantastic interactive tutorial on this sort of thing, check out https://learngitbranching.js.org/

Extra-credit for the future

I'm guessing there are only a handful of meaningful logical changes in all those commits. It's usually difficult to read 30 or 45 commit-sized merge requests. (Imagine if you had to read someone else's branch like that!)

Keep working on your Git-fu, and working toward having one commit for each one meaningful logical change. Look online for guides on how Git interactive rebase can help you reorganize and simplify the commits in your branches.

Kache
  • 15,647
  • 12
  • 51
  • 79
1

The answer by Kache is a very complete and fleshed out answer. However, I would like to point out a simple technique (using git reset) that has been left out:
1. Create a new branch (anotherBranch) using (git branch) from the branch you wish to edit (exampleBranch). (It appears you have already done this)
2.git checkout exampleBranch
3.git reset C30 where C30 is actually the SHA of the last commit to be included in your MR
4.git push --force to overwrite the remote branch with your local branch.
5. Don't forget to also push anotherBranch with the work you've done on it.

I assumed you are working on a branch you have write access to. But beware of git push --force as it can be quite destructive if misused. Always make sure you are not force pushing to someone else's branch or even master.

T. Laferriere
  • 77
  • 1
  • 6