2

I have a fork of another organization's repository. I'm at the the latest tag in the repo, which is not the head, and I've created a branch from that tag which will never be pushed upstream. That's why I consider the branch private.

I've made commits to my private branch and am using that code in my production environment. When a new tag is made to the upstream repository, I want to be able to pull their changes.

However, I'd like to always keep my commits in a neat stack on top of their last tag. I don't want to merge then, since my commits will end up living far back in the history and I want to see them right on top so I can work with them easily when I use certain tools on my repository.

So really, I want a "floating" branch, one that I can transplant to an arbitrary point when I bring the upstream changes to my repository.

[edits] I don't believe I can use rebase, however, since that's a history-rewriting operation. You see, I use my repository on two machines, my development and production. I make my commits on the development machine, push to github, then pull to production. All of this has nothing to do with the changes on the upstream repository that I originally forked from.

I'm not entirely clear on transplanting, cherry-picking or whatever other tool might be suited. Whichever tool it is though, I gather it shouldn't rewrite history. From my reading, I see that rewriting repo history is a no-no when pushing . So I'm not sure what commands I should be using that will transplant a branch without rewriting history.

If I were using mercurial, I might consider something like a version-controlled mq. I don't know the analogous solution for git, if there is one, or whether there is another, better-suited tool for git.

[edit]

After evaluating the responses I got here, I finally determined that cherry-picking was the right answer. In all cases, rebase removes history, and since this is a shared repository, removing history is unacceptable, at least according to every source I've read.

Cherry-picking, however, copies the commit to my working tree without removing it from its original location. So I can plant a copy of my changes on top of the latest tag and have them in a nice neat pile.

For the record, I also tried to do this with Mercurial, by using the hg-git extension which lets you use hg to clone a git repository. This had pluses and minuses. The biggest minus was that when I finished using it, it couldn't push. hg-git works happily until that point, then tells you that it doesn't push with hg 1.9. Bogus, to say the least. The other minus was that cloning and pulling a large set of changes is extremely slow. However, mq and TortoiseHg's merge conflict resolution tools are a vast improvement over git cherry-pick and Smartgit's merge conflict resolution. I wish hg-git could have worked.

I guess that in the end, "floating" wasn't such a good description for my change branch, since the result is to copy it rather than move it. Sorry for my perhaps poor description, I was still figuring out exactly what the options were. Thanks for the help.

Binary Phile
  • 2,538
  • 16
  • 16
  • 5 years later, but still: if your reference point in Mercurial was MQ, which is a reimplementation of quilt, then you could have tried reimplementations for git: stgit, guilt or topgit. Anyway, looks like MQ itself is about-to-be-deprecated; but Mercurial has better substitutes ( http://gregoryszorc.com/blog/2014/06/23/please-stop-using-mq/ ) . In git, rebasing might do a lot of what you want, but comparatively it's still is a lot of busywork for some quilt-like use cases. https://stackoverflow.com/questions/952651/git-equivalent-to-hg-mq – hmijail Jul 08 '16 at 11:41
  • 1
    @hmijail Sure. Nowadays I use stgit if I need to. "stg pull" is the answer I was looking for. – Binary Phile Jul 12 '16 at 14:29
  • That's actually interesting. If you tried rebasing and finally decided that stgit was the way to go, maybe you could explain why as an addendum to your question? (or maybe even as a new answer). I keep finding myself wanting to try stgit or friends, because it feels like rebase still leaves much to do. – hmijail Jul 12 '16 at 14:53

2 Answers2

3
git fetch
git rebase --onto latesttag previoustag yourbranch

Conflicts have to be dealt with and entirely depend on what you are doing with files that may have changed from one tag to the next. In particular, if someone has eliminated some code that you change, you will have to address this and make sure that the code you changed can now be applied elsewhere. There is no silver bullet for this. Once you resolved your conflicts and everything works,

git add -A
git rebase --continue

Rinse repeat.

To add, if you are doing this to just be able to deploy, a "floating branch" may not be the best method for dealing with this. Consider these alternates:

  1. deploy scripts that manipulate the files to ensure the deploy works.
  2. smudge/clean scripts that modify files when populating the working directory. (https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes#_keyword_expansion)

Your floating branch seems like it is there only for the sake of your own environment and hence should not be part of the project.

ax.
  • 58,560
  • 8
  • 81
  • 72
Adam Dymitruk
  • 124,556
  • 26
  • 146
  • 141
  • Understood about conflicts. The changes I make are deliberately minimal, so conflicts should also be minimal. I'm capable of handling them in such a case, although the warning is appreciated. My question on history still stands...what happens when I push/pull to github and my local repo no longer has history that's been pushed previously? Or do these rebase commands leave my history intact, copying the branch instead of cutting/pasting? – Binary Phile Dec 28 '11 at 21:01
  • I'll be playing with both sets of commands given so far, yours and fge's. Thanks both. – Binary Phile Dec 28 '11 at 21:34
0

You describe the job of git rebase --onto here.

Scenario:

  • git fetch from the remote;
  • by security, make a new copy: git branch newbranch currentbranch;
  • say the old tag, which you are currently based on, is oldtag, and the new tag is newtag;
  • "transplant": git rebase --onto newtag oldtag newbranch;
  • resolve conflicts if need be;
  • git branch -D currentbranch;
  • git branch -m newbranch currentbranch.

However, as to rewriting history, you will -- of your branch, not of the origin repository, you don't have write access to it, do you?

fge
  • 119,121
  • 33
  • 254
  • 329
  • My fork of the repo is on github. I use it on two machines, development and production. I make my commits on the development machine, push to github then pull to production. This means that my commits live in multiple copies of the repo. Doesn't that preclude rebasing then? – Binary Phile Dec 28 '11 at 20:48
  • @AdamDymitruk if you have noticed, I created `newbranch` first, out of `currentbranch`. It is in the case that rebasing on `newtag` led to too complicated conflicts to solve: you still had your original branch. – fge Dec 28 '11 at 20:51
  • see my answer. If your custom code is editing files that may have been substantially changed or removed entirely, rebasing won't be trivial. – Adam Dymitruk Dec 28 '11 at 20:52
  • @AdamDymitruk of course... This is not the reason for a downvote, my solution works anyway. Bah. – fge Dec 28 '11 at 20:53
  • crap. SO won't let me "un-downvote" now :( Can someone upvote this to compensate? – Adam Dymitruk Dec 28 '11 at 20:58
  • upvoted. fge - I've read several places that when you remove history that has previously been pushed elsewhere, synchronization gets confused. At the very least, the next time you pull, the deleted history should reappear. It's not clear what the gods of version control do in such a case, but it doesn't please them, from what I understand. – Binary Phile Dec 28 '11 at 21:14
  • @BinaryPhile this it true, if you work with others on a remote, you should never rewrite history on this remote. You can do anything you want on _your_ local repo, just not on the remote. This is why I love gitolite, since it is able to disallow non fast-forward pushes (ie, "history rewriting pushes"), to restrict branch namespacing for different persons etc. There is no one way to do development right, but as far as I am concerned, gitolite is a must for all development models where the number of developers reaches double digit numbers. – fge Dec 28 '11 at 21:21