Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell Git that two commits are actually the same in a disjoint history?

I have a Git repo that is clone from another Git repo that is a clone from a giant SVN repo. We can update the other Git repo from SVN and commit from it to SVN, but with another user.

I want to publish my local commits to the SVN repo directly, with my own user.

This is what I tried: I manually created the git-svn branch, adding this to .git/config

[branch "master"]
[svn-remote "svn"]
        url = https://url/to/svn/trunk/repo_name
        fetch = :refs/remotes/git-svn

Then git svn fetch, downloaded 32k commits.

But I ended up with two disjoint histories:

  1. One from Git:
    1. Starting at commit 674c35a that represents the state of the SVN repo at the point of the original clone.
    2. The branch master is always synchronized with SVN (through the other Git repo).
    3. The branch dev have our current developments, that should be merged to master (usually squashed), and then committed back to the SVN repo.
  2. One for the SVN repo:
    1. Starts with the proper initial commit.
    2. It has 30k+ commits.
    3. The commit that Git originally cloned from SVN [fb1b9c7] (but only with diff from the previous commits, not the entire repo as a start commit).
    4. Then the same commits (100+) that should be common to git/origin/master.

How can I tell Git that the starting commit (674c35a) is actually the same as a SVN commit (fb1b9c7)? So Git can somehow understand that the commits in master, after the clone, are actually the same as git-svn?

I have tried to rebase with --onto, as explained here, but that wasn't really what I wanted (the commits are not in top of the branch).

like image 485
RSFalcon7 Avatar asked Sep 30 '16 16:09

RSFalcon7


People also ask

How do I find the difference between two commits?

To see the changes between two commits, you can use git diff ID1.. ID2 , where ID1 and ID2 identify the two commits you're interested in, and the connector .. is a pair of dots. For example, git diff abc123.. def456 shows the differences between the commits abc123 and def456 , while git diff HEAD~1..

Can we compare two commits in git?

You can also compare two arbitrary commits in your repository or its forks on GitHub in a two-dot diff comparison. To quickly compare two commits or Git Object IDs (OIDs) directly with each other in a two-dot diff comparison on GitHub, edit the URL of your repository's "Comparing changes" page.

Which command checks difference between the previous two commits?

You can run the git diff HEAD command to compare the both staged and unstaged changes with your last commit.

Which command would you use to view the history of commits?

The most basic and powerful tool to do this is the git log command. By default, with no arguments, git log lists the commits made in that repository in reverse chronological order; that is, the most recent commits show up first.


1 Answers

I believe I have a method which should work for this in my blog post Grafting History with Git which for the purposes of complying with site rules I'll summarize here :

Current state :

  • Two git repos with diverging histories but one origin

Target state :

  • One git repo with two branches representing those diverging histories

  • Convert both histories into Git branches (I think you've already got this)
  • Find the point of divergence by comparing logs and seeing when the tree hash changes
    • Get a list of the tree-ids and commit-ids on each branch using git log --reverse --format="%T %H" and save this to a file
    • Compare the lists to see where the tree hash diverges (I use a diff program that can do columns, you could just use awk and diff though)
  • Check out the point of divergence on the target repo branch and make a new branch
  • Fetch all the objects from source into target
  • For each revision in the original source, create a new revision on target that
    • Is a checkout of the tree of the foreign revision using git read-tree -um $TREEID
    • Uses the original commit message using git commit --reuse-message $ORIGINAL_COMMIT

Or ... cat your list of tree-id + commit-id into this script.

#!/bin/bash
# graft script
while read TREE COMMIT
do
 git read-tree -um $TREE
 git commit --reuse-message $COMMIT
done
like image 164
Adrian Avatar answered Sep 23 '22 03:09

Adrian