diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+### 0.21.3
+
++ Do not add nodes in overrides if a node with the same name already exists, fixes [#171](https://github.com/haskell-gi/haskell-gi/issues/171).
+
 ### 0.21.2
 
 + Do not free `Ptr Word8` types after performing the call to C,
diff --git a/DocTests.hs b/DocTests.hs
--- a/DocTests.hs
+++ b/DocTests.hs
@@ -1,17 +1,20 @@
 import Test.DocTest
+import System.Process
 
 main :: IO ()
-main = doctest [ "-XCPP", "-XOverloadedStrings", "-XRankNTypes", "-XLambdaCase"
-               , "-ilib"
-               -- For the autogenerated Data.GI.CodeGen.GType (hsc)
-               , "-idist/build"
-               , "dist/build/lib/c/enumStorage.o"
-               -- For gobject-introspection
-               , "-lgirepository-1.0"
-               , "-lgobject-2.0"
-               , "-lglib-2.0"
-               -- The actual modules to test
-               , "Data.GI.CodeGen.GtkDoc"
-               , "Data.GI.CodeGen.ModulePath"
-               , "Data.GI.CodeGen.SymbolNaming"
-               , "Data.GI.CodeGen.Haddock" ]
+main = do
+  gobjectIntrospectionLibs <- pkgConfigLibs "gobject-introspection-1.0"
+  doctest $ [ "-XCPP", "-XOverloadedStrings", "-XRankNTypes", "-XLambdaCase"
+            , "-ilib"
+            -- For the autogenerated Data.GI.CodeGen.GType (hsc)
+            , "-idist/build"
+            , "dist/build/lib/c/enumStorage.o"
+            ] ++ gobjectIntrospectionLibs ++
+            -- The actual modules to test
+            [ "Data.GI.CodeGen.GtkDoc"
+            , "Data.GI.CodeGen.ModulePath"
+            , "Data.GI.CodeGen.SymbolNaming"
+            , "Data.GI.CodeGen.Haddock" ]
+
+pkgConfigLibs :: String -> IO [String]
+pkgConfigLibs pkg = words <$> readProcess "pkg-config" ["--libs", pkg] ""
diff --git a/cmdline/haskell-gi.hs b/cmdline/haskell-gi.hs
--- a/cmdline/haskell-gi.hs
+++ b/cmdline/haskell-gi.hs
@@ -38,7 +38,7 @@
 import Data.GI.CodeGen.OverloadedSignals (genOverloadedSignalConnectors)
 import Data.GI.CodeGen.Overrides (Overrides, parseOverridesFile, nsChooseVersion, filterAPIsAndDeps, girFixups, pkgConfigMap)
 import Data.GI.CodeGen.ProjectInfo (licenseText)
-import Data.GI.CodeGen.Util (ucFirst, utf8ReadFile, utf8WriteFile, terror)
+import Data.GI.CodeGen.Util (ucFirst, utf8WriteFile, terror)
 
 data Mode = GenerateCode | Dump | Labels | Signals | Help
 
@@ -232,9 +232,9 @@
 process :: Options -> [Text] -> IO ()
 process options names = do
   let extraPaths = optSearchPaths options
-  configs <- traverse utf8ReadFile (optOverridesFiles options)
   setupTypelibSearchPath (optSearchPaths options)
-  parseOverridesFile (concatMap T.lines configs) >>= \case
+  configs <- traverse parseOverridesFile (optOverridesFiles options)
+  case mconcat <$> sequence configs of
     Left errorMsg -> do
       hPutStr stderr "Error when parsing the config file(s):\n"
       hPutStr stderr (T.unpack errorMsg)
diff --git a/haskell-gi.cabal b/haskell-gi.cabal
--- a/haskell-gi.cabal
+++ b/haskell-gi.cabal
@@ -1,5 +1,5 @@
 name:                haskell-gi
-version:             0.21.2
+version:             0.21.3
 synopsis:            Generate Haskell bindings for GObject Introspection capable libraries
 description:         Generate Haskell bindings for GObject Introspection capable libraries. This includes most notably
                      Gtk+, but many other libraries in the GObject ecosystem provide introspection data too.
@@ -47,7 +47,11 @@
     build-depends: semigroups == 0.18.*
 
   extensions:          CPP, ForeignFunctionInterface, DoAndIfThenElse, LambdaCase, RankNTypes, OverloadedStrings
-  ghc-options:         -Wall -fno-warn-missing-signatures -fwarn-incomplete-patterns -fno-warn-name-shadowing
+  ghc-options:         -Wall -fwarn-incomplete-patterns -fno-warn-name-shadowing
+
+  if impl(ghc >= 8.0)
+     ghc-options: -Wcompat
+
   c-sources:           lib/c/enumStorage.c
 
   build-tools:         hsc2hs
@@ -115,7 +119,9 @@
   type:          exitcode-stdio-1.0
   ghc-options:   -threaded
   main-is:       DocTests.hs
-  build-depends: base, doctest >= 0.8
+  build-depends: base
+               , process
+               , doctest >= 0.8
 
 executable haskell-gi
   main-is:             haskell-gi.hs
@@ -123,6 +129,9 @@
 
   extensions:          CPP, OverloadedStrings, LambdaCase
   ghc-options:         -Wall -fno-warn-name-shadowing
+
+  if impl(ghc >= 8.0)
+     ghc-options: -Wcompat
 
   build-depends:       base >= 4.7 && < 5,
                        text >= 1.0,
diff --git a/lib/Data/GI/CodeGen/API.hs b/lib/Data/GI/CodeGen/API.hs
--- a/lib/Data/GI/CodeGen/API.hs
+++ b/lib/Data/GI/CodeGen/API.hs
@@ -489,20 +489,29 @@
 
 -- | Add the given subnode to any nodes matching the given path
 girAddNode :: GIRPath -> XML.Name -> XML.Node -> XML.Node
-girAddNode (spec:rest) newNode n@(XML.NodeElement elem) =
+girAddNode (spec:rest) newNode n@(XML.NodeElement element) =
   if specMatch spec n
   then case rest of
     -- Matched the full path, add the new child node.
     [] -> let newElement = XML.Element { elementName = newNode
                                        , elementAttributes = M.empty
                                        , elementNodes = [] }
-          in XML.NodeElement (elem {XML.elementNodes =
-                                    XML.elementNodes elem <>
+              -- We only insert if not present, see #171. For
+              -- convenience when writing the override files, we
+              -- ignore the namespace when comparing.
+              nodeElementName (XML.NodeElement e) =
+                (Just . nameLocalName . elementName) e
+              nodeElementName _ = Nothing
+              nodeNames = mapMaybe nodeElementName (XML.elementNodes element)
+          in if nameLocalName newNode `elem` nodeNames
+             then n
+             else XML.NodeElement (element {XML.elementNodes =
+                                    XML.elementNodes element <>
                                      [XML.NodeElement newElement]})
     -- Still some selectors to apply.
-    _ -> XML.NodeElement (elem {XML.elementNodes =
+    _ -> XML.NodeElement (element {XML.elementNodes =
                                 map (girAddNode rest newNode)
-                                 (XML.elementNodes elem)})
+                                 (XML.elementNodes element)})
   else n
 girAddNode _ _ n = n
 
diff --git a/lib/Data/GI/CodeGen/CabalHooks.hs b/lib/Data/GI/CodeGen/CabalHooks.hs
--- a/lib/Data/GI/CodeGen/CabalHooks.hs
+++ b/lib/Data/GI/CodeGen/CabalHooks.hs
@@ -19,7 +19,7 @@
 import Data.GI.CodeGen.ModulePath (toModulePath)
 import Data.GI.CodeGen.Overrides (parseOverridesFile, girFixups,
                                   filterAPIsAndDeps)
-import Data.GI.CodeGen.Util (ucFirst, utf8ReadFile)
+import Data.GI.CodeGen.Util (ucFirst)
 
 import Control.Monad (when, void)
 
@@ -47,10 +47,9 @@
                 defaultConfHook (gpd, hbi) flags = do
   setupTypelibSearchPath []
 
-  ovsData <- case overrides of
-               Nothing -> return ""
-               Just fname -> utf8ReadFile fname
-  ovs <- parseOverridesFile (T.lines ovsData) >>= \case
+  ovs <- case overrides of
+    Nothing -> return mempty
+    Just fname -> parseOverridesFile fname >>= \case
          Left err -> error $ "Error when parsing overrides file: "
                      ++ T.unpack err
          Right ovs -> return ovs
diff --git a/lib/Data/GI/CodeGen/Callable.hs b/lib/Data/GI/CodeGen/Callable.hs
--- a/lib/Data/GI/CodeGen/Callable.hs
+++ b/lib/Data/GI/CodeGen/Callable.hs
@@ -261,15 +261,17 @@
                          _ -> undefined
           Nothing -> badIntroError $ "freeInArgs: do not understand " <> tshow arg
 
--- Return the list of actions freeing the memory associated with the
+-- | Return the list of actions freeing the memory associated with the
 -- callable variables. This is run if the call to the C function
 -- succeeds, if there is an error freeInArgsOnError below is called
 -- instead.
+freeInArgs :: Callable -> Map.Map Text Text -> ExcCodeGen [Text]
 freeInArgs = freeInArgs' freeInArg
 
--- Return the list of actions freeing the memory associated with the
+-- | Return the list of actions freeing the memory associated with the
 -- callable variables. This is run in case there is an error during
 -- the call.
+freeInArgsOnError :: Callable -> Map.Map Text Text -> ExcCodeGen [Text]
 freeInArgsOnError = freeInArgs' freeInArgOnError
 
 -- Marshall the haskell arguments into their corresponding C
diff --git a/lib/Data/GI/CodeGen/Code.hs b/lib/Data/GI/CodeGen/Code.hs
--- a/lib/Data/GI/CodeGen/Code.hs
+++ b/lib/Data/GI/CodeGen/Code.hs
@@ -236,6 +236,7 @@
   }
 
 -- | Clean slate for `CGState`.
+emptyCGState :: CGState
 emptyCGState = CGState {
   cgsCPPConditionals = []
   }
diff --git a/lib/Data/GI/CodeGen/Conversions.hs b/lib/Data/GI/CodeGen/Conversions.hs
--- a/lib/Data/GI/CodeGen/Conversions.hs
+++ b/lib/Data/GI/CodeGen/Conversions.hs
@@ -795,6 +795,8 @@
     _ -> haskellType t
 isoHaskellType t = haskellType t
 
+-- | Foreign (C) type associated to one of the basic types.
+foreignBasicType :: BasicType -> TypeRep
 foreignBasicType TBoolean  = "CInt" `con` []
 foreignBasicType TUTF8     = "CString" `con` []
 foreignBasicType TFileName = "CString" `con` []
diff --git a/lib/Data/GI/CodeGen/Overrides.hs b/lib/Data/GI/CodeGen/Overrides.hs
--- a/lib/Data/GI/CodeGen/Overrides.hs
+++ b/lib/Data/GI/CodeGen/Overrides.hs
@@ -30,9 +30,9 @@
 import Data.GI.CodeGen.API
 import qualified Text.XML as XML
 import Data.GI.CodeGen.PkgConfig (tryPkgConfig)
-import Data.GI.CodeGen.Util (tshow)
+import Data.GI.CodeGen.Util (tshow, utf8ReadFile)
 import Data.GI.GIR.XMLUtils (xmlLocalName, xmlNSName,
-                             GIRXMLNamespace(CGIRNS, GLibGIRNS))
+                             GIRXMLNamespace(CGIRNS, GLibGIRNS, CoreGIRNS))
 
 data Overrides = Overrides {
       -- | Ignored elements of a given API.
@@ -84,6 +84,8 @@
 instance Sem.Semigroup Overrides where
   (<>) = concatOverrides
 
+-- | Addition of overrides is meaningful.
+concatOverrides :: Overrides -> Overrides -> Overrides
 concatOverrides a b = Overrides {
       ignoredAPIs = ignoredAPIs a <> ignoredAPIs b,
       sealedStructs = sealedStructs a <> sealedStructs b,
@@ -130,14 +132,14 @@
 -- encode this in a monad.
 type Parser a = WriterT Overrides (StateT ParserState (ExceptT Text IO)) a
 
--- | Parse the given config file (as a set of lines) for a given
--- introspection namespace, filling in the configuration as needed. In
--- case the parsing fails we return a description of the error
--- instead.
-parseOverridesFile :: [Text] -> IO (Either Text Overrides)
-parseOverridesFile ls =
-    runExceptT $ flip evalStateT emptyParserState $ execWriterT $
-              mapM (parseOneLine . T.strip) ls
+-- | Parse the given overrides file, filling in the configuration as
+-- needed. In case the parsing fails we return a description of the
+-- error instead.
+parseOverridesFile :: FilePath -> IO (Either Text Overrides)
+parseOverridesFile fname = do
+  overrides <- utf8ReadFile fname
+  runExceptT $ flip evalStateT emptyParserState $ execWriterT $
+    mapM (parseOneLine . T.strip) (T.lines overrides)
 
 -- | Parse a single line of the config file, modifying the
 -- configuration as appropriate.
@@ -170,6 +172,7 @@
     withFlags $ parseDocsUrl u
 parseOneLine (T.stripPrefix "if " -> Just s) = parseIf s
 parseOneLine (T.stripPrefix "endif" -> Just s) = parseEndif s
+parseOneLine (T.stripPrefix "include " -> Just s) = parseInclude s
 parseOneLine l = throwError $ "Could not understand \"" <> l <> "\"."
 
 -- | Ignored elements.
@@ -316,6 +319,7 @@
                    [n] -> return (xmlLocalName n)
                    ["c", n] -> return (xmlNSName CGIRNS n)
                    ["glib", n] -> return (xmlNSName GLibGIRNS n)
+                   ["core", n] -> return (xmlNSName CoreGIRNS n)
                    _ -> throwError ("Could not understand xml name \""
                                     <> a <> "\".")
 
@@ -387,6 +391,13 @@
             case flags s of
               _:rest -> put (s {flags = rest})
               [] -> throwError ("'endif' with no matching 'if'.")
+
+-- | Parse the given overrides file, and merge into the given context.
+parseInclude :: Text -> Parser ()
+parseInclude fname = liftIO (parseOverridesFile $ T.unpack fname) >>= \case
+  Left err -> throwError ("Error when parsing included '"
+                         <> fname <> "': " <> err)
+  Right ovs -> tell ovs
 
 -- | Filter a set of named objects based on a lookup list of names to
 -- ignore.
diff --git a/lib/Data/GI/GIR/XMLUtils.hs b/lib/Data/GI/GIR/XMLUtils.hs
--- a/lib/Data/GI/GIR/XMLUtils.hs
+++ b/lib/Data/GI/GIR/XMLUtils.hs
@@ -66,13 +66,14 @@
 lookupAttr attr element = M.lookup attr (elementAttributes element)
 
 -- | GIR namespaces we know about.
-data GIRXMLNamespace = GLibGIRNS | CGIRNS
+data GIRXMLNamespace = GLibGIRNS | CGIRNS | CoreGIRNS
                      deriving Show
 
 -- | Return the text representation of the known GIR namespaces.
 girNamespace :: GIRXMLNamespace -> Text
 girNamespace GLibGIRNS = "http://www.gtk.org/introspection/glib/1.0"
 girNamespace CGIRNS = "http://www.gtk.org/introspection/c/1.0"
+girNamespace CoreGIRNS = "http://www.gtk.org/introspection/core/1.0"
 
 -- | Lookup an attribute for an element, given the namespace where it lives.
 lookupAttrWithNamespace :: GIRXMLNamespace -> Name -> Element -> Maybe Text
