In order to avoid linking code that isn't used, the linker works from left to right, keeping track of functions that are undefined. If a library defines some function that hasn't been used in preceding code, then the function is presumed to be unneeded, so the definition is ignored and not linked into the code.
Thus, in your example,
clang -ggdb -Wall -Werror hello.c -lcs50 -o hello
Let's suppose that
get_string is the only CS50 Library function used in
hello.c. The linker first sees a compiled version of
hello.c with a reference to a function named
get_string that hasn't yet been defined. The linker therefore remembers to look for a definition of
get_string in subsequent libraries. Then, the linker gets to the
-lcs50 part. Here it finds the
get_string definition that it was looking for. However, the CS50 Library also contains many other functions that aren't used by
hello.c, such as
get_int isn't going to be used, then there's no point in linking it into the final compiled
hello executable. That would just waste space. So, the linker simply forgets about
get_int and the other unused functions.
If, on the other hand, we write
clang -ggdb -Wall -Werror -lcs50 hello.c -o hello
…then the first thing the linker sees is the CS50 Library and its various function definitions. But it doesn't know that any of these functions will be used, so it forgets all of them! Then the linker moves on to
hello.c. At this point, it sees that
get_string is needed. Alas, the previous definition of
get_string has already been forgotten. The linker will at this point make a note that it needs a definition for
get_string, but since this is the last file that we're linking, we won't find a definition, and the linking process fails.