TL;DR
Running COPY . /app on top of an image with but slightly outdated source code creates a new layer as large as the whole source code,
Docker caching works per layer / instruction in the Dockerfile. In this case the files used in that layer (everything in the build-context (.)) are modified, so the layer needs to be rebuilt.
If there's specific parts of the code that don't change often, you could consider to add those in a separate layer, or even move those to a "base image"
FROM mybaseimage
COPY ./directories-that-dont-change-often /somewhere
COPY ./directories-that-change-often /somewhere
It may take some planning or restructuring for this to work, depending on your project, but may be worth doing.