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.
Related
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.
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?
I cloned a large SVN repository (nearly 8,000 commits) and it seems to be OK.
Since then, the commit messages of about 20 Subversion commit messages have been changed to correct a typo. This was done legitimately. However, git svn fetch does not pull the updated commit messages. It still displays the old outdated commit message.
Is there a way to fix this? Preferably in a clean way and without hacking my local git repository too much?
I've tried git svn fetch -r 1234 (where 1234 is a known revision number). But no luck.
from http://git-scm.com/docs/git-svn:
git svn reset
Undoes the effects of fetch back to the specified revision. This allows
you to re-fetch an SVN revision.
[...]
Follow reset with a fetch and then git
reset or git rebase to move local
branches onto the new tree.
So in your case, if revision 1234 is the first one that had its commit message changed, you would do
$ git svn reset -p 1234
$ git svn fetch
If anything is different, including the commit message, then the new commit is a totally different object, with a new SHA1, so as it says, you'll need to rebase any branches you might have onto the appropriate rewritten commit.
How can I do a git svn reset to HEAD revision without specifying the revision number?
It sounds like what you want is not a git svn reset but a simple git checkout. I'm not sure what you mean when you say you reverted to an older revision, but it may have been something like
$ git log
# scan through the log looking for a particular commit.
# You find it and its SHA1 is abc123...
$ git checkout abc123
You are now in 'detached HEAD' state blah blah blah...
Now, HEAD (in your git repository) refers to the commit with SHA1 abc123, whereas HEAD (in the central SVN repository) refers to the newest commit on the SVN repository. If you have things set up in a fairly typical way, then you can just do git checkout master and then git svn rebase and you're back to normal working conditions.
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.