How about adding a level for the ordering.
create table #ObjectRelations
(
Id varchar(20),
NextId varchar(20)
)
insert into #ObjectRelations values ('G', 'B')
insert into #ObjectRelations values ('A', 'B')
insert into #ObjectRelations values ('B', 'C')
insert into #ObjectRelations values ('B', 'X')
insert into #ObjectRelations values ('C', 'E')
insert into #ObjectRelations values ('C', 'D')
insert into #ObjectRelations values ('E', 'F')
insert into #ObjectRelations values ('D', 'F')
;
WITH Objects --(lvl, Id, NextId)
AS
( -- This is the 'Anchor' or starting point of the recursive query
SELECT 1 AS Lvl,
rel.Id,
rel.NextId
FROM #ObjectRelations rel
WHERE rel.Id = 'A' OR rel.Id = 'G'
UNION ALL -- This is the recursive portion of the query
SELECT lvl + 1,
rel.Id,
rel.NextId
FROM #ObjectRelations rel
INNER JOIN Objects -- Note the reference to CTE table name (Recursive Join)
ON rel.Id = Objects.NextId
)
SELECT distinct o.*
FROM Objects o
Order by lvl
drop table #ObjectRelations