This is because of the property of the recursive function which returns to it parent calling function after getting executed.
e.g.
20
/ \
10 30
this is a tree with its root as 20. Now walking through the inOrderTraverseTree code of yours:
1. call inOrderTraverseTree(20)
2. check for root being null, here 20 is not null.
3. call inOrderTraverseTree(10) {left of 20 is 10}
4. check for root being null, here 10 is not null.
5. call inOrderTraverseTree(null) {left of 10 is null}
6. check for root being null, here it is null.Hence exit out of "if",return to calling function,i.e step 4{root=10}
7. print root,i.e print 10.
8. call inOrderTraverseTree(null) {right of 10 is null}
9. check for root being null, here it is null.Hence exit out of "if",return to calling function,i.e step 3{root=20}.{complete execution for root=10 is completed}
10.print root,i.e print 20.
11.call inOrderTraverseTree(30){right of 20 is 30}
12.check for root being null, here 30 is not null.
13.call inOrderTraverseTree(null){left of 30 is null}
14. check for root being null, here it is null.Hence exit out of "if",return to calling function,i.e step 12{root=30}
15. print root,i.e print 30.
16. call inOrderTraverseTree(null) {right of 30 is null}
17. check for root being null, here it is null.Hence exit out of "if",return to calling function,i.e step 11{root=20}.{complete execution for root=30 is completed}
with this the complete execution of inOrderTraverseTree call with root 20 is also completed and the value printed is 10 (in step 7), 20 (in step 10), 30 (in step 15): 10 20 30.
Now coming to "code that makes the traverse method go one level up from the lowest left child" : you can see this happening in step 9. Where the leftmost child is returned to its parent calling function when the complete function cycle for leftmost child is fully executed. This is the main property of recursive function.