5

I have two git branches: Alpha and Beta and I need to create next commit on the branch Alpha so its project state would be exactly the same like on branch Beta. Without merge.

I understand that every git commit - on a logical level - is a complete and immutable project state + some metadata. So I just need branch Alpha to have the same state of files like Beta does.

It would be another commit (with different hash), and one branch tip wouldn't reference another.

Adam
  • 1,796
  • 18
  • 19
  • You may read the manual of [git-format-patch](https://git-scm.com/docs/git-format-patch) and [git-apply](https://git-scm.com/docs/git-apply) to achieve your goal without merge – TravorLZH Aug 18 '18 at 06:44
  • @TravorLiu, yes its possible to create a patch based on their diff, and the apply it. But it I believe there should be a simpler and more elegant way. Thanks! – Adam Aug 18 '18 at 07:02

2 Answers2

6
c=$(git commit-tree Beta^{tree} -p Alpha -m 'foo')
test $c && git update-ref refs/heads/Alpha $c

git commit-tree creates a new commit, whose tree is the same with Beta's tip's and whose parent is Alpha's tip.

git update-ref makes Alpha point at the new commit.

ElpieKay
  • 27,194
  • 6
  • 32
  • 53
  • Exactly what I needed! Just one-line command `git update-ref refs/heads/Alpha $(git commit-tree Beta^{tree} -p Alpha -m 'foo')` – Adam Aug 18 '18 at 07:50
  • 2
    That's exactly the right solution. (And it shows that it helps learning the Git object model, [which is really not that complicated](https://stackoverflow.com/a/44872194/2988).) A commit is a pointer to a tree, a set of pointers to parent commits, and some metadata. You already have the tree, all you need is to construct the commit. – Jörg W Mittag Aug 18 '18 at 08:14
3

But it I believe there should be a simpler and more elegant way.

There is a way which does not involve patches: reset --hard followed by reset --soft.

  • First, mark the current HEAD of your branch: we will need to move that HEAD without modifying Alpha, so let's create a new temporary branch called 'tmp' where Alpha is.

    git checkout Alpha
    git checkout -b tmp
    
  • Then we go back to an Beta HEAD commit with the right content.

    git reset --hard Beta 
    

That resets the index (and working tree) to the right content, but that also moves HEAD. However, that moves tmp HEAD, not Alpha HEAD.

  • move back tmp HEAD to where mAlphaaster is, but without modifying the index or the working tree (which are representing what we need for a new commit)

    git reset --soft Alpha
    
  • make a new commit, on top of Alpha/tmp HEAD, which represents the right content (Beta HEAD commit content).

    git commit -m "new commit, image of an old one"
    
  • Finally, force Alpha to be where tmp is: one new commit later.

    git branch -M tmp Alpha
    git checkout Alpha
    git branch -d tmp
    

Now a regular git push is enough, any collaborator can simply pull as usual, and still get the old reset content.

git push
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250