what's pending in git svn? - git-svn

I'd like to use git rebase -i to squash the commits that I have pending before dcommitting. It's not really obvious to me, however, which commits are hanging out there. Is there a git svn option I'm missing, or some other recipe?

You can see which Git commits git svn dcommit will push using git svn dcommit --dry-run. You could try something like the below to show the logs of all the commits that would be pushed:
git show $(git svn dcommit --dry-run | tail -n+2 | awk '{print $3}')

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

Enabling SVN tracking in a git clone of a git-svn clone that didn't start at revision 1?

Suppose I have a git svn clone that I created like this:
$ mkdir foo
$ cd foo
$ git svn clone -s -r 100:HEAD http://svn.example.com/project
and then I git clone it like this:
$ cd ..
$ git clone foo bar
$ cd bar
So now bar has foo as its origin.
How do I make bar track the original SVN server? The git-svn man page provides an example of the case where the original git svn clone includes the full revision history, but this doesn't seem to cover the case that the original git svn clone doesn't start from r1. When I try the various things I see described, what git svn fetch does is always start a disconnected history starting at r1.

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.

How do you view the status of your svn-git repo?

I understand how to initialize a git-svn repo, create a branch, do some work, merge branch, then use git svn rebase and git svn dcommit to push back to the svn repo. But between these two commands, how can you get a status of what is different between the two repos? Something like a git status that tells you that you have x number of files that have been changed.
Just do a diff between your branch and upstream.
git diff --stat git-svn/master..master
Obviously, you'll have to change the branch names to whatever's applicable for your setup.
The only real way I know is to run 'git svn dcommit -n' (or git svn dcommit --dry-run) which will usually give you output like this:
$git svn dcommit --dry-run
Committing to http://yourserver.com/trunk ...
diff-tree bc923cb54847fa340d094c3da1ebd66b8fb0e63e~1 bc923cb54847fa340d094c3da1ebd66b8fb0e63e
diff-tree a05c8be4af7f82dc4de5b4778e2b58203c75eebd~1 a05c8be4af7f82dc4de5b4778e2b58203c75eebd
And then you can 'git show bc923cb54847fa340d094c3da1ebd66b8fb0e63e' to view that diff.

How to commit a Git repo to an empty repo SVN server?

I have setup an empty svn on a server and I have been working on locally making commits along the way. Now I wish to commit my repo to an svn server. For this I tried:
git-svn checkout http://remote.svn.server.com
git-svn dcommit
Git complains that:
Use of uninitialized value in concatenation (.) or string at /usr/bin/git-svn line 411.
Committing to ...
Unable to determine upstream SVN information from HEAD history
Since I started on my local computer first, and the repo online is empty, I can't find any info on how to make this work.
I needed something like this recently and the process is relatively straightforward.
There's good tutorial by Brandon Dimcheff, "Commit a linear git history to subversion" (replaces old broken link), which these steps are based on.
As of Git version 1.6.3 these are the steps:
$ svnadmin create svn_repository
$ svn mkdir -m "Initial setup" file:///full/path/to/svn_repository/trunk
$ mkdir gitrepo && cd gitrepo
$ git init
$ echo 'Hello from Git' > file.txt
$ git add file.txt
$ git commit -m "Hello from Git"
$ git svn init --trunk=trunk file:///full/path/to/svn_repository/
$ git svn fetch
$ git branch -a # Lists remotes/trunk
$ git rebase --onto remotes/trunk --root master
# => Applying: Hello from Git etc.
$ git svn dcommit
# => Committing to ... Committed r2 ... etc
You can do a svn checkout of svn_repository now and see your Git repo.
Here is what I would do:
git-svn clone http://remote.svn.server.com otherdir
Then in other dir pull the changes locally from your previous dir. Then you should have a git repo that is "connected" via git-svn and you should be able to use dcommit on it.
This might also be a useful read.