Let's think about it this way for a second
Companies often have resources (legacy infrastructure) that were manually created before Terraform came into the picture — deleting those and recreating them fresh with Terraform risks production downtime. `terraform import <resource_address> <existing_id>` tells the state 'this resource already exists' without deleting or recreating it (you still have to write the config block yourself — the import command only fills in the state). Drift refers to the situation where what's in Terraform's state/config is one thing, and what's actually on the cloud provider (because someone manually changed it) is another — running `terraform plan` finds and reports drift.
Let's connect this to a real scenario
If someone manually changes instance_type in the AWS console (t3.micro → t3.large), running `terraform plan` will find and report the drift — 'the config says t3.micro, but the actual state is t3.large.' Running `terraform apply` treats the Terraform config (t3.micro) as the 'true source' and reconciles the actual state to match it (essentially reverting the manual change).
Let's look at it together
# Import an existing S3 bucket into Terraform's state
terraform import aws_s3_bucket.legacy my-existing-bucket-name
# After import, check for drift
terraform plan
# If someone manually changed something in the console,
# plan will show the difference here$ terraform import aws_s3_bucket.legacy my-existing-bucket-name
aws_s3_bucket.legacy: Importing from ID "my-existing-bucket-name"...
aws_s3_bucket.legacy: Import complete!5-minute try-it
Try running the `terraform import` command's syntax (`terraform import <address> <id>`) yourself against a local_file resource (a file you already created manually beforehand).
A quick word of caution
Don't auto-run `apply` the moment drift is detected — read the plan carefully first, since sometimes a manual change was intentional (an emergency fix), and you may need to update the config instead.