I used to say, "Just refresh the page!", which causes the browser to pull new files from the server. This is also know as invalidating a cached object.
But occasionally, I get a particularly savvy client who asks, "well, won't all of the returning visitors have to do the same thing?" In which case, I'd explain the whole cache expiration date thing, and how after a certain amount of time, the browser will grab new assets from the server (according to the cache headers I've setup for their site). This is usually okay, as long as your changes don't significantly affect the layout of the site.
As time went on, I had realized that I needed to make it a matter practice to ensure that certain assets were invalidated when going live. But, how can this be done? If a browser already has an expiration date for an asset, it won't check that asset again until "time's up". Hence, it will continue to load it from the cache. So, what we need to do is "trick" the browser into thinking it's a completely new asset.
Method #1 – Renaming the asset
I used this method for a while, until I realized it caused SEO issues with images, particularly, 404 Not Found responses.
You might have guessed that this method involves simply renaming the asset on the file system and, correspondingly, in your code. The browser will then realize that it doesn't have file with this name inside it's cache, and will continue to download it from the server.
As I stated above, this method has one very big pitfall, it breaks links.
If you rename image.jpg to image1.jpg, any links to that image will have been broken. Some might consider this a good thing, as it certainly keeps other webmasters from using images on your server! But, consider the impact on Google Image Search (and other image search engines).
Method #2 – Adding a query string parameter
The better approach, which still causes browser's to download a new version of the asset from the server, is to simply append or change a query string parameter on the image source attribute. For example:
<img src="http://www.mysite.com/images/myimage.jpg" alt="" />
<img src="http://www.mysite.com/images/myimage.jpg?v=1" alt="" />
By incrementing a single query string parameter with each revision to the asset, you keep the browser coming back to the server, instead of to it's cache to load the asset.
AFAIK, any query param just stops caching that resource — You should look into proper cache-control headers using something like etags.
ETags are a great option, no argument there. But, query params don’t prevent caching of the resource, they simply tell the browser that we’ve got a different resource. This is the reason that libraries such as jQuery will add a date-based query string to an AJAX call if you specify not to use a cached version.