Remotely Track the Current Branch in Git
I'm moving my continuous testing to a dedicated server (autotest slows down my local laptop too much). What I'd like is for my testing server (which happens to be running CruiseControl.rb) to be continuously getting my latest (committed) changes via Git -- ideally, without any changes to my own workflow. I am the only developer working on this project.
Prior to getting the testing server, I had:
- My laptop as my main development system
- Multiple branches in my local repository.
- A local working copy, pointing to one of the branches. I switch between branches frequently (usually for new features).
- A GitHub account, to which I frequently push local branches to mirrored remote branches. (This is mostly for use an offsite backup; I'm not sharing any code for my current project). I try to push to GitHub at least at the end of every workday, though I occasionally forget.
I'd like to keep all of that intact. On top of that, I now have:
- The test server
- ...running CruiseControl.rb
- A clone of my laptop repository on my test server. (Currently it's not cloning GitHub)
- A local working copy on the test server, from which CC is building/testing.
- This working copy points to one particular Git branch (of course)
I've been trying to have my test server automatically get whatever branch I'm working on on my laptop working copy and build from that. (That would mimic autotest's continuous testing without eating up system resources).
Things I've tried without success:
- git checkout origin/HEAD: this gets the files fine but breaks CruiseControl because it doesn't like the "branchless" working copy.
- git checkout --track -b a_branch origin/a_branch: this works fine for getting files, and CC likes it, but it sticks the testing server to a particular branch. When switching branches on the laptop I'll effectively stop testing my current work.
- git checkout -开发者_Go百科-track -b my_testing_branch origin/HEAD: this also gets buildable files, but it suffers from the same problem as the command above. Creating a branch from origin/HEAD only gets the HEAD for the "default" branch, so it's also sticky.
Is there any way I can get a good remote continuous testing system (with or without git branches) that doesn't involve major changes to my workflow?
Another option is to write a hook that notifies the test server of new code to pull. In particular, a post-commit
hook is probably a better route. Then, every time you commit you can inform the test server of what to pull and from which branch.
You could have a dedicated testing branch on which you merge your current branch work.
You can force replacing the content of that branch with the commit of the current working branch (see git merge -s ours, what about “their” question).
Then on the CI server, you initialize it with:
$ git fetch laptopRepo
$ git checkout -b testingBranch laptopRepo/testingBranch
It implies one first step on the laptop side to publish some current work to test.
This isn't the greatest solution but it's something...
The test server can run git remote show origin
to see which branch is currently active on your laptop. E.g.,
$ git remote show origin * remote origin Fetch URL: blade:/var/scratch/code Push URL: blade:/var/scratch/code HEAD branch: foo Remote branches: foo tracked bar tracked qux tracked
So, the origin repository is currently on the foo
branch.
I haven't seen a low level command that will give you that directly so you may have to parse it out from this (perhaps someone will have a better way). Example,
$ b=$(git remote show origin | grep "HEAD branch" | awk -F: '{print $2}') $ echo $b foo
Now, since origin/foo
will act similar to origin/HEAD
(no local branch) and your CruiseControl doesn't like that you should probably just create a local branch on the testing machine and simply hard-reset it to the latest location:
$ b=$(git remote show origin | grep "HEAD branch" | awk -F: '{print $2}') $ git reset --hard origin/$b
Note, this is slightly fragile since HEAD
me not always be what you think it is. For example, during a rebase HEAD
will be moving backward and forward. If your testing server checks HEAD
on your laptop during a rebase it could get some invalid or undesired location.
I've think got a pretty good solution by inverting the relationship between the two systems. Instead of having the test server pull from the laptop's repository, I could have the laptop push changes out to the server to be tested.
First I add a remote on the laptop's repo:
git remote add testing <url of testing server>
Then, whenever I have code for testing, I do a push:
git push -f testing HEAD:master
This will work from whatever branch I'm currently on. The -f ensures that I'll blow away whatever is already in that branch; I won't have to worry about any ancestry.
This won't actually put the latest code in a working copy, but CruiseControl's polling can solve that. I could also have a server-side hook that updates a working copy and runs the test suite (I wouldn't even need CC at that point).
I'll probably want to add a combined commit+push command to a script or alias; that will give me my one-command commit & test. If for some reason I want to do a commit without a test push (or vice versa), then I have those options too.
Host on GitHub and use their post-recieve hooks. That's how services like Devver and RunCodeRun do it.
I've considered skipping past git and going to a shared folder/NFS/rsync solution, but that has one major problem: it's not triggered by / limited to commits, so I'll end up getting false-positive broken builds while I'm in the middle of typing something.
精彩评论