Git: mark two commits on two branches as same though history of commits on the two is different - git-merge

I have a dev branch and a master branch.
We make development on dev branch till the release date.
On release day, we rebase all the changes on dev branch "commit-by-commit" to master branch and merge them.
This way we retain the history of commits on master branch as well.
In the past, (PROBABLE REASON) once I forgot to do this commit-by-commit and pushed several commits (say A,B,C) on dev as a single commit to master(A').
Now, everytime I do the said activity in para1, it finds A' as differing and tries to rebase corresponding commits A,B,C to master.
I wish to overcome this by indicating to git
- that repo content pointed by C on dev branch is same as that pointed by A' on master. OR
- that repo content pointed by J on dev branch is same as that pointed by J on master.
With this I hope the tool to pick only new commits.
Is there a way?
dev : /A-B-C =D-E-F=G-H-I-J
master: Z-Y- A'=D-E-F=G-H-I-J
= indicates a merge from dev to master branch for release
/ indicates dev being branched out

git checkout dev
git checkout -b temp-dev [SHA for C]
git checkout master
git checkout -b temp-master [SHA for Y]
git rebase temp-dev
git branch -D master
git branch -D temp-dev
git branch -m temp-master master
git tag [your previous release]
... do the same for F ...
git rebase dev
git tag [your new release]
If I understand you correctly, something like this, maybe?

Related

How to solve merge conflict in a approved review in gerrit?

I made a change in gerrit which was code reviewed and after 7 revisions approved. But, now it cannot be merged and trying to rebase in gerrit website is not working due to merge conflict. How can I resolve this merge conflict and merge the same approved change and not create a new one.
(Full steps from cloning the repo would be appreciated.)
1) Clone the Gerrit repository
git clone https://USER#GERRIT-SERVER/a/REPO-FULL-PATHNAME
2) Go to the change page on Gerrit and copy the checkout patch command
git fetch https://USER#GERRIT-SERVER/a/REPO-FULL-PATHNAME refs/changes/XX/YYYYY/Z && git checkout FETCH_HEAD
3) Rebase the change
git rebase origin/BRANCH
4) Solve the conflicts
git mergetool
5) Continue the rebase
git rebase --continue
Repeat the steps 4 and 5 until the end of conflicts
git commit --amend
Note: Keep the same Change-Id
6) Send the new patchset to Gerrit
git push origin HEAD:refs/for/BRANCH
The accepted solution works but I personally disagree with this workflow. It is unnecessarily cumbersome.
I prefer a workflow with exactly one merge and therefore less steps.
Clone the Gerrit repository if not already available
git clone https://[USER]#[GERRIT-SERVER]/a/[REPO-FULL-PATHNAME]
Checkout the Gerrit patch
git fetch https://[USER]#[GERRIT-SERVER]/a/[REPO-FULL-PATHNAME] refs/changes/46/12346/N && git checkout FETCH_HEAD
Soft-reset the change and stash it
git reset --soft HEAD~1 && git stash
Checkout branch or the Gerrit patch you want to rebase onto
git checkout origin/BRANCH
# or fetch other Gerrit patch:
# git fetch https://[USER]#[GERRIT-SERVER]/a/[REPO-FULL-PATHNAME] refs/changes/45/12345/N && git checkout FETCH_HEAD
Unstash the previously stashed changes
git stash pop
Solve the conflicts with your favourite 3-way merge tool.
Commit the merged changes - NOT (!!) amend them - and use the same Change-Id from the merged patch in the message:
git commit -am "[COMMIT-MESSAGE]\
\
Change-Id: [FORMER-CHANGE-ID]"
Send the new patchset to Gerrit
git push origin HEAD:refs/for/BRANCH
Done. One merge!
I additionally use the gitreview tool. That makes it extra easy. Steps 2, 3, 4 and 5 then can be chained.
git review -d 12346 && git reset --soft HEAD~1 && git stash && git review -d 12345 && git stash pop

Update my git branch followed by svn repository changes in git-svn

I'm using 'git svn' to clone source from svn repository.
And use a branch to create new features.
The git log graph like
S1-S2+S3-S4-S5-S6-S7 (master)
+B1-B2-...-B9 (new-feature)
The newest svn version is 'S7' and the latest local branch is 'B9'. I want the graph be rebased like
S1-S2+S3-S4-S5-S6-S7+ (master)
+B2-B9 (new-feature)
My operation commands:
git checkout master
git svn rebase # it updated master to S7
git checkout new-feature
git rebase master
It will occurs many blank space conflicts, as I know that's because B1,B3...B8 have already checked in svn by other people. Is there smarter method to let me just keep some my patches which is not just space conflict? Here the B2,B9 are just examples. In fact, I don't know which patches should be replaced or merged or skipped in advanced. I just know, some of the svn check in are duplicate with some of Bx patches.
You should be able to simply do git svn rebase on your new-feature branch, no need to change to master iirc.
Regarding discarding the B2-B9 commits, you could e. g. do git checkout -B new-feature B1 && git cherry-pick B9. This will recreate the new-feature branch from B1 and cherry-pick the B9 commit. Or you do an interactive rebase like git rebase -i B1, then remove the lines for B2-B8 in the todo list and leave the editor. Or you can do a non-interactive rebase like git rebase --onto B1 B8 new-feature.

how to get all branchs from repository?

I'm a new user with git, and I use gitBash.
When I execute $git clone http:..../name.git, the master branch of name is downloading. But when I execute $git branch -a I just see the master branch, no others.
But I have some others branchs... Why I can't see all branches ? How do that ?
thx.
git branch -a only displays local branches you have already checked out.
You want to use git branch -r (where -r stands for remote). This should list all the remote branches available (I can't test this right now, but I'm fairly certain it works).

git rebase --onto causes conflict — why?

I'm trying a
git rebase --onto master myremote/master~21 myremote/master
to add the latest 21 commits from a remote repository on mine.
What git tells me is that there's a conflict — but how's that possible?
In my understanding it's just taking that 21 commits and applying them on top of my master. How can there be conflicts?
Thanks for help!
I'm doing that btw because somehow I messed up my git-svn repository (the remote), and there's 21 commits which I don't manage to commit to subversion. So I'm trying with a fresh git-svn clone, in which I'm adding those 21 commits.
There is conflict if:
master has commit that are not in myremote/master.
those commits include common files/changes with one the last 21 myremote/master commits.
If somehow the fresh git-svn clone has different SHA1 than the previous git-svn repo, then there is no close common ancestors, and the chances of conflicts are that much higher.
See "How to identify conflicting commits by hash during git rebase?" for illustrations of conflicts during a rebase.
One way to reset your local master to myremote/master would be to:
git checkout -b tmp myremote/master # local tmp branch from myremote/master HEAD.
git merge -s ours master # ignore completely master content
git checkout master
git merge tmp # fast-forward to tmp HEAD
If you hadn't made any changes in your local master before fetching myremote/master, this should work.

Why does git-svn dcommit leave duplicate commits in my git repo? Can I stop it doing that?

My typical git-svn workflow is:
git checkout -b story-xyz
git commit -a -m "work"
git commit -a -m "more work"
git checkout master
git svn fetch
git merge remotes/trunk
git checkout story-xyz
git rebase master (sometimes with -i)
git checkout master
git merge story-xyz
At this point I have my master and story-xyz branches pointing to the same commit, one or more commits ahead of remotes/trunk. Everything since remotes/trunk is in one linear history.
last svn commit [remotes/trunk] <--- work <--- more work [master, story-xyz]
I then run
git svn dcommit
I expected to see the commits between remotes/trunk and master become Subversion revisions, and end up with a single linear history with remotes/trunk, master and story-xyz all pointing to the latest revision, like so:
last svn commit <--- work <--- more work [master, story-xyz, remotes/trunk]
My Subversion revisions go in fine, but I end up with a two-branched structure. The common root of the branch is the Subversion HEAD before I committed. Both branches contain the same series of commits, in the sense that they contain the same diffs. The branch story-xyz is at the head of one branch, remotes/trunk and master at the other:
last svn commit <--- work <--- more work [master, remotes/trunk]
|
\- work <--- more work [story-xyz]
The git commits that I had before running git svn dcommit are on the lower branch (story-xyz), with my git commit messages, git user name and email, and git commit timestamps. The commits on the upper branch are new git commits. They use my Subversion username, the timestamp when I ran the dcommit, and the commit messages have the git-svn-id field appended to them.
This is all OK, and I can carry on working. The problem is that I look in gitk and see what looks like an unmerged branch story-xyz. It's pretty hard to tell the difference between a story branch that I have merged back into master, and one that I haven't. The most obvious way to spot it is the duplicate commit messages. I could delete the story-xyz branch, but that feels like I'm not using git properly and I've lost some of my history.
Am I missing something that would stop git-svn from doing this? Or is this just one of the ways that interacting with Subversion dilutes the power and freedom of git?
I don't think you're really missing anything. You might be doing some unnecessary work, though. In this case, you have two pointers to the "more work" commit, and you are asking git-svn to move one of them. The other one still stays where it is.
You don't really need the master branch. Git-svn doesn't care about what branch you are dcommiting. IIRC, it uses the first svn-remote it can find among the ancestors of the current commit.
I'll offer another version of the workflow:
git checkout -b story-xyz remotes/trunk
git commit -a -m "work"
git commit -a -m "more work"
git svn fetch
git rebase remotes/trunk (with -i, perhaps)
git svn dcommit
This should give you a tree without the extra branch. You need to be careful with fast-forward merges, though.