Never suffer from shadowing problems again!  And you don't need to learn about contexts, either.

Concept and code by Matthew Cook

The code that should be in your init.m

ForwardContext::usage = 
      "ForwardContext[symbol, oldcontext, newcontext] removes the symbol \
oldcontext<>symbol, and then sets the removed symbol (which may still exist \
in definitions, such as In[5]:=...) to point to the symbol \
newcontext<>symbol.  It also makes the InputForm of the old symbol (now \
removed) remain as just \"symbol\", so that the definitions don't start \
looking peculiar.";

SetAttributes[ClearQ, {HoldFirst, Listable}]ClearQ@sym_ := 
      Flatten[ToExpression[#<>"Values"]@sym&/@{"Default", 
              "Down", "Format", "N", "Own", "Sub", 
              "Up"}] === {}Protect@ClearQ;

\(Unprotect@Message; 
UnforwardedQ[_, _, _] := True\)ForwardContext[sym_String, old_String, new_String] /; 
        UnforwardedQ[sym, old, new] := 
      Module[{command}, UnforwardedQ[sym, old, new] = False; 
        command := 
          ToExpression[
            "Remove@"<>old<>sym<>";"<>old<>sym<>":="<>new<>sym<>
              ";", InputForm, Hold]; First@command; Unprotect@Removed; 
        Format[Removed@sym, InputForm] := Format[sym, OutputForm]; 
        Protect@Removed]$ShadowEntrySafe = True;
Message[sym_::shdw, name_, oldcons_, newcon_]:=If[$ShadowEntrySafe,With[{sname = First@name, scon = First@newcon, 
                  ocon = DeleteCases[First@oldcons, First@newcon]},Block[{$ShadowEntrySafe = False},If[ToExpression["Global`ClearQ@"<>#<>sname],ForwardContext[sname, #, scon]; 
                            Message[sym::fwd, name, #, newcon],Message[sym::shdwvl,name,#,newcon,With[{zv = sname, zo = #, zn = scon},"fix it"]]]&/@ocon]]]Protect@Message;

\(General::fwd = 
      "The existing symbol `` in context `` is being forwarded to context ``."; 
General::shdwvl = 
      "Definitions have been made for symbol `` in context `` which will shadow new definitions in context ``.
** Press `` to use only the new definitions."; \)

A example of how it helps

This is an example of a typical session where one forgets to load a package.

We make some shorthand definitions because we are a lazy typer:

{ppq, sp, cert} = {ProvablePrimeQ, SmallPrime, Certificate}

We set SmallPrime to a small prime:

SmallPrime = 37;

We wonder if that's really how SmallPrime is supposed to be used:

?SmallPrime

What?  Oh, we forgot to load the necessary package!
Let's load it:

<<NumberTheory`PrimeQ`

(Don't press the "fix it" button quite yet.)

It didn't automatically forward SmallPrime, since that would erase the definition you made:

?? SmallPrime

But you don't want that definition.  You want to use the "real" SmallPrime.

Now press the "fix it" button in the warning message above.

Now our definition is gone, and SmallPrime is what we wanted it to be:

?? SmallPrime

What about sp?  We defined it before we loaded the real SmallPrime, but this has been fixed behind the scenes for us:

?sp

In fact, everything works just fine:

ppq[12345678910987654321, cert -> True, sp -> 10^20]

As we can see, we are not suffering in the slightest from having loaded the package after using some of its symbols.

☺ Have fun using packages!  -Matthew Cook