2

I was able to sync files from one RepoA to RepoB using 'fetch' and 'checkout' to my master and handling the conflicts (if any). but this approach caused me to make a 'merge-commit' on RepoB.

Is there any way to do it without that commit id being generated? I wanted to schedule all the commits and then sync then on a regular basis through chron-task.

I also looked into git-daemon and post-commit hooks. If this can be done please provide an example.

Initial state of Repos:
Initial state of Repos

After applying merge:
After applying merge

After resetting to last commit (Create File02.txt):
After resetting to last commit (Create File02.txt)

6
  • 4
    "Handling conflicts" means creating data about how the conflicts are resloved. This data has to be stored somewhere, and that somewhere is the merge commit. Even without conflicts, the merge commit is what makes two diverged branches converge again to incorporate both changesets. So, in the general case, you can't avoid the merge commit. Commented Mar 8, 2017 at 13:45
  • Can rebase help to alter the commit history in order to conclude with the last commit instead of the final merge-commit? Commented Mar 9, 2017 at 4:25
  • @PratyushRaizada Yup, easiest is to simply use git pull --rebase, see my answer for details. Commented Mar 10, 2017 at 7:27
  • Do the two "Initial commit"s have different hashes? Then the observed behaviour is to be expected, but this comment space is too narrow to explain ;) Commented Mar 14, 2017 at 6:50
  • The two "initial commit"s (A and B) have indeed different hashes, so git must do a merge Commented Mar 14, 2017 at 6:56

3 Answers 3

3

Because of the way git stores and addresses data, a given commit ID can only possibly store one particular tree - which is to say, one set of directories with one set of files with one specific set of content in each file.

(Technically you can argue that this is not true, but realistically it will never happen that two commits with different trees have the same commit hash.)

So when you merge, whether you resolve a conflict or not, unless the result of the merge is exactly the same as one of the original commits (which generally only happens when one commit was an ancestor of the other and fast-forward is allowed), a new commit has to be created.

So when you sync two repos, if that includes syncing branches in which each repo contains changes that the other hasn't yet seen, it is not possible to avoid creating a new commit.

UPDATE - In the comments, a follow-up question was raised: "Can rebase help to alter the commit history in order to conclude with the last commit instead of the final merge-commit?"

While that question could be interpreted a couple ways, the answer is in any case "no". Setting aside warnings about using rebase if any of the repositories involved are shared with other users, it won't do what you seem to be asking of it.

First, understand that rebase does not change the order of commits. It is impossible to change the order of commits. When you do an interactive rebase and change the order of the to-do list, what happens is that completely new commits are created (with a new commit id for each) in order to apply the same changes in a different order.

In fact, by default you might not notice this, but the original commits are still left right where they were before the rebase. (Try tagging HEAD before doing this type of rebase and then run something like gitk --all to see the results.)

The reason you can't reorder commits is similar to the reason you can't merge in changes without creating a new commit ID. Everything about the commit is encoded in the commit ID. That includes its tree as I noted before; it also includes the ID of the parent commit (and so, transitively, the entire lineage of commits that led up to the current commit).

So in general:

  • If you have a repo and you incorporate new changes into it that previously it did not contian, then every commit that reflects those changes will have a new ID not previously seen in the repo.

  • If you have two repos, and each of them contains changes that are not in the other, then every commit that reflects the merged changes from both will be a new commit with a new ID not previously seen in either repo.

Sign up to request clarification or add additional context in comments.

13 Comments

Can rebase help to alter the commit history in order to conclude with the last commit instead of the final merge-commit?
Short answer: no. I'll update with the long answer.
I've provided an update to try to address this. If you want further detail or think I've misunderstood the question, I suggest trying this: draw up a diagram showing the contents of each repo before the merge, and a diagram showing what you'd like the final repo to look like. Post that, and we can directly address whether it's possible, if so how to do it, and if not why not.
Thanks I'll post shortly
Hi Mark! I found a work around for the commit removal, by restoring the repo to the last author commit I can now ignore the Merge-commit by using the command "git reset --hard fb62ef635b07afaf719ba15841579ed12e1224b0"
|
1

You can use git pull --rebase, which will rebase your local commits on top of the remote head. You may of course encounter other conflicts you have to fix, but still you won't have any additional merge-commits. You can also git config pull.rebase true in order to always achieve this via git pull. Be aware of a rebase's consequences though, e.g. you shouldn't have pushed anything rebased before.

Related SO questions:

4 Comments

Hmm... I think I read the question differently, but depending on what you're really trying to accomplish this may be a good solution.
@MarkAdelsberger Yes, unfortunately the question is not entirely clear without some example history. Hopefully both our answers are useful for others :)
@TobiasKienzler I've uploaded some images as an example to show the problem. You can find it in Mark's answer. Hope it clarifies. (I'm a new to using this platform or else I could've posted it in the question itself)
@PratyushRaizada You can edit your question, there is an image upload function as well - aw, I see, you need some rep first, don't worry that'll happen soon. I'll edit it in for you.
-1

After merging the repo the last merge-commit can be removed by simply restoring the Repo's state to the last commit from the parent repo.

Use command:

git log --format="%H" -n 1 ---> To get the last commit id from the parent repo

git reset --hard fb62ef635b07afaf719ba15841579ed12e1224b0 bring back the state of Repo to previous state

fb62ef635b07afaf719ba15841579ed12e1224b0 is the commit id from the previous state

3 Comments

Instead of a fixed commit id, you can use HEAD^ for the previous commit or e.g. HEAD~4 for the commit 4 commits ago. But a hard reset is usually a dangerous procedure making you loose all uncommitted changes; you might want to consider a rebase instead. Or use git stash first.
I thought of considering HEAD^ but in case there are no commits, one genuine commit will get erased. Thanks for introducing 'git stash'!
You're welcome - but note that your answer means not just loosing the merge commit, but also all your own commits since the last pull! Luckily for you, git does keep a reflog so you can find those commits again if you act soon.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.