You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: book/07-git-tools/sections/submodules.asc
+133-8Lines changed: 133 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -511,7 +511,138 @@ To https://github.com/chaconinc/MainProject
511
511
512
512
As you can see there, Git went into the DbConnector module and pushed it before pushing the main project. If that submodule push fails for some reason, the main project push will also fail.
513
513
514
-
With these tools, submodules can be a fairly simple and effective method for developing on several related but still separate projects simultaneously.
514
+
===== Merging Submodule Changes
515
+
516
+
If you change a submodule reference at the same time as someone else, you may run into some problems. That is, if the submodule histories have diverged and are committed to diverging branches in a superproject, it may take a bit of work for you to fix.
517
+
518
+
If one of the commits is a direct ancestor of the other (a fast-forward merge), then Git will simply choose the latter for the merge, so that works fine.
519
+
520
+
Git will not attempt even a trivial merge for you, however. If the submodule commits diverge and need to be merged, you will get something that looks like this:
521
+
522
+
[source,shell]
523
+
----
524
+
$ git pull
525
+
remote: Counting objects: 2, done.
526
+
remote: Compressing objects: 100% (1/1), done.
527
+
remote: Total 2 (delta 1), reused 2 (delta 1)
528
+
Unpacking objects: 100% (2/2), done.
529
+
From https://github.com/chaconinc/MainProject
530
+
9a377d1..eb974f8 master -> origin/master
531
+
Fetching submodule DbConnector
532
+
warning: Failed to merge submodule DbConnector (merge following commits not found)
533
+
Auto-merging DbConnector
534
+
CONFLICT (submodule): Merge conflict in DbConnector
535
+
Automatic merge failed; fix conflicts and then commit the result.
536
+
----
537
+
538
+
So basically what has happened here is that Git has figured out that the two branches record points in the submodule's history that are divergent and need to be merged. It explains it as ``merge following commits not found'', which is confusing but we'll explain why that is in a bit.
539
+
540
+
To solve the problem, you need to figure out what state the submodule should be in. Strangely, Git doesn't really give you much information to help out here, not even the SHAs of the commits of both sides of the history. Fortunately, it's simple to figure out. If you run `git diff` you can get the SHAs of the commits recorded in both branches you were trying to merge.
541
+
542
+
[source,shell]
543
+
----
544
+
$ git diff
545
+
diff --cc DbConnector
546
+
index eb41d76,c771610..0000000
547
+
--- a/DbConnector
548
+
+++ b/DbConnector
549
+
----
550
+
551
+
So, in this case, `eb41d76` is the commit in our submodule that *we* had and `c771610` is the commit that upstream had. If we go into our submodule directory, it should already be on `eb41d76` as the merge would not have touched it. If for whatever reason it's not, you can simply create and checkout a branch pointing to it.
552
+
553
+
What is important is the SHA of the commit from the other side. This is what you'll have to merge in and resolve. You can either just try the merge with the SHA directly, or you can create a branch for it and then try to merge that in. We would suggest the latter, even if only to make a nicer merge commit message.
554
+
555
+
So, we will go into our submodule directory, create a branch based on that second SHA from `git diff` and manually merge.
556
+
557
+
[source,shell]
558
+
----
559
+
$ cd DbConnector
560
+
561
+
$ git rev-parse HEAD
562
+
eb41d764bccf88be77aced643c13a7fa86714135
563
+
564
+
$ git branch try-merge c771610
565
+
(DbConnector) $ git merge try-merge
566
+
Auto-merging src/main.c
567
+
CONFLICT (content): Merge conflict in src/main.c
568
+
Recorded preimage for 'src/main.c'
569
+
Automatic merge failed; fix conflicts and then commit the result.
570
+
----
571
+
572
+
We got an actual merge conflict here, so if we resolve that and commit it, then we can simply update the main project with the result.
It can be a bit confusing, but it's really not very hard.
605
+
606
+
Interestingly, there is another case that Git handles.
607
+
If a merge commit exists in the submodule directory that contains **both** commits in it's history, Git will suggest it to you as a possible solution. It sees that at some point in the submodule project, someone merged branches containing these two commits, so maybe you'll want that one.
608
+
609
+
This is why the error message from before was ``merge following commits not found'', because it could not do *this*. It's confusing because who would expect it to **try** to do this?
610
+
611
+
If it does find a single acceptable merge commit, you'll see something like this:
612
+
613
+
[source,shell]
614
+
----
615
+
$ git merge origin/master
616
+
warning: Failed to merge submodule DbConnector (not fast-forward)
617
+
Found a possible merge resolution for the submodule:
CONFLICT (submodule): Merge conflict in DbConnector
627
+
Automatic merge failed; fix conflicts and then commit the result.
628
+
----
629
+
630
+
What it's suggesting that you do is to update the index like you had run `git add`, which clears the conflict, then commit. You probably shouldn't do this though. You can just as easily go into the submodule directory, see what the difference is, fast-forward to this commit, test it properly, and then commit it.
631
+
632
+
[source,shell]
633
+
----
634
+
$ cd DbConnector/
635
+
$ git merge 9fd905e
636
+
Updating eb41d76..9fd905e
637
+
Fast-forward
638
+
639
+
$ cd ..
640
+
$ git add DbConnector
641
+
$ git commit -am 'Fast forwarded to a common submodule child'
642
+
----
643
+
644
+
This accomplishes the same thing, but at least this way you can verify that it works and you have the code in your submodule directory when you're done.
645
+
515
646
516
647
==== Submodule Tips
517
648
@@ -710,10 +841,4 @@ Then, when you switch back, you get an empty `CryptoLibrary` directory for some
710
841
711
842
It's important to note that submodules these days keep all their Git data in the top project's `.git` directory, so unlike much older versions of Git, destorying a submodule directory won't lose any commits or branches that you had.
712
843
713
-
714
-
715
-
==== Alternatives to Submodules
716
-
717
-
===== Subtree
718
-
719
-
git-subtree
844
+
With these tools, submodules can be a fairly simple and effective method for developing on several related but still separate projects simultaneously.
0 commit comments